1
0
mirror of https://github.com/medigor/example-native-api-rs.git synced 2025-07-03 00:58:13 +02:00

разные улучшения

This commit is contained in:
medigor
2022-12-11 16:52:11 +03:00
parent a49eff49d1
commit 9d7b8ad772
4 changed files with 196 additions and 61 deletions

View File

@ -14,6 +14,7 @@ const PROPS: &[&[u16]] = &[
const METHODS: &[&[u16]] = &[&utf16_null!("Method1")]; const METHODS: &[&[u16]] = &[&utf16_null!("Method1")];
pub struct Addin1 { pub struct Addin1 {
test: i32,
prop_i32: i32, prop_i32: i32,
prop_f64: f64, prop_f64: f64,
prop_bool: bool, prop_bool: bool,
@ -25,6 +26,7 @@ pub struct Addin1 {
impl Addin1 { impl Addin1 {
pub fn new() -> Addin1 { pub fn new() -> Addin1 {
Addin1 { Addin1 {
test: 12345,
prop_i32: 0, prop_i32: 0,
prop_f64: 0.0, prop_f64: 0.0,
prop_bool: false, prop_bool: false,
@ -44,10 +46,6 @@ impl Addin for Addin1 {
true true
} }
fn get_info(&mut self) -> u16 {
1000
}
fn done(&mut self) {} fn done(&mut self) {}
fn register_extension_as(&mut self) -> &'static [u16] { fn register_extension_as(&mut self) -> &'static [u16] {
@ -68,7 +66,7 @@ impl Addin for Addin1 {
fn get_prop_val(&mut self, num: usize, val: ReturnValue) -> bool { fn get_prop_val(&mut self, num: usize, val: ReturnValue) -> bool {
match num { match num {
0 => val.set_i32(111226), 0 => val.set_i32(self.test),
1 => val.set_i32(self.prop_i32), 1 => val.set_i32(self.prop_i32),
2 => val.set_f64(self.prop_f64), 2 => val.set_f64(self.prop_f64),
3 => val.set_bool(self.prop_bool), 3 => val.set_bool(self.prop_bool),
@ -87,6 +85,13 @@ impl Addin for Addin1 {
fn set_prop_val(&mut self, num: usize, val: &ParamValue) -> bool { fn set_prop_val(&mut self, num: usize, val: &ParamValue) -> bool {
match num { match num {
0 => match val {
ParamValue::I32(x) => {
self.test = *x;
true
}
_ => false,
},
1 => match val { 1 => match val {
ParamValue::I32(x) => { ParamValue::I32(x) => {
self.prop_i32 = *x; self.prop_i32 = *x;
@ -140,7 +145,7 @@ impl Addin for Addin1 {
fn is_prop_writable(&mut self, num: usize) -> bool { fn is_prop_writable(&mut self, num: usize) -> bool {
match num { match num {
0 => false, 0 => true,
1 => true, 1 => true,
2 => true, 2 => true,
3 => true, 3 => true,

121
src/addin2.rs Normal file
View File

@ -0,0 +1,121 @@
use crate::ffi::{Addin, Connection, ParamValue, ReturnValue};
use utf16_lit::utf16_null;
pub struct Addin2 {
test1: i32,
}
impl Addin2 {
pub fn new() -> Addin2 {
Addin2 { test1: 12345 }
}
}
impl Drop for Addin2 {
fn drop(&mut self) {
}
}
impl Addin for Addin2 {
fn init(&mut self, _interface: &'static Connection) -> bool {
true
}
fn done(&mut self) {
}
fn register_extension_as(&mut self) -> &'static [u16] {
&utf16_null!("Class2")
}
fn get_n_props(&mut self) -> usize {
1
}
fn find_prop(&mut self, name: &[u16]) -> Option<usize> {
const TEST1: &[u16] = &utf16_null!("Test1");
match name {
TEST1 => Some(0),
_ => None,
}
}
fn get_prop_name(&mut self, num: usize, _alias: usize) -> Option<&'static [u16]> {
if num == 0 {
Some(&utf16_null!("Test1"))
} else {
None
}
}
fn get_prop_val(&mut self, num: usize, val: ReturnValue) -> bool {
match num {
0 => {
val.set_i32(self.test1);
true
}
_ => false,
}
}
fn set_prop_val(&mut self, _num: usize, _val: &ParamValue) -> bool {
false
}
fn is_prop_readable(&mut self, _num: usize) -> bool {
true
}
fn is_prop_writable(&mut self, _num: usize) -> bool {
false
}
fn get_n_methods(&mut self) -> usize {
0
}
fn find_method(&mut self, _name: &[u16]) -> Option<usize> {
None
}
fn get_method_name(&mut self, _num: usize, _alias: usize) -> Option<&'static [u16]> {
None
}
fn get_n_params(&mut self, _num: usize) -> usize {
0
}
fn get_param_def_value(
&mut self,
_method_num: usize,
_param_num: usize,
_value: ReturnValue,
) -> bool {
true
}
fn has_ret_val(&mut self, _method_num: usize) -> bool {
false
}
fn call_as_proc(&mut self, _method_num: usize, _params: &[ParamValue]) -> bool {
false
}
fn call_as_func(
&mut self,
_method_num: usize,
_params: &[ParamValue],
_val: ReturnValue,
) -> bool {
false
}
fn set_locale(&mut self, _loc: &[u16]) {}
fn set_user_interface_language_code(&mut self, _lang: &[u16]) {}
}

View File

@ -219,7 +219,11 @@ struct TVariant {
pub trait Addin { pub trait Addin {
fn init(&mut self, interface: &'static Connection) -> bool; fn init(&mut self, interface: &'static Connection) -> bool;
fn get_info(&mut self) -> u16;
/// default 2000, don't use version 1000, because static objects are created
fn get_info(&mut self) -> u16 {
2000
}
fn done(&mut self); fn done(&mut self);
fn register_extension_as(&mut self) -> &'static [u16]; fn register_extension_as(&mut self) -> &'static [u16];
fn get_n_props(&mut self) -> usize; fn get_n_props(&mut self) -> usize;
@ -354,8 +358,7 @@ unsafe extern "system" fn find_prop<T: Addin>(
component: &mut LanguageExtenderBase<T>, component: &mut LanguageExtenderBase<T>,
name: *const u16, name: *const u16,
) -> c_long { ) -> c_long {
let len = strlen(name); let name = get_str(name);
let name = from_raw_parts(name, len);
match component.addin.find_prop(name) { match component.addin.find_prop(name) {
Some(i) => i as c_long, Some(i) => i as c_long,
None => -1, None => -1,
@ -432,8 +435,7 @@ unsafe extern "system" fn find_method<T: Addin>(
component: &mut LanguageExtenderBase<T>, component: &mut LanguageExtenderBase<T>,
name: *const u16, name: *const u16,
) -> c_long { ) -> c_long {
let len = strlen(name); let name = get_str(name);
let name = from_raw_parts(name, len);
match component.addin.find_method(name) { match component.addin.find_method(name) {
Some(i) => i as c_long, Some(i) => i as c_long,
None => -1, None => -1,
@ -551,8 +553,7 @@ struct LocaleBaseVTable<T: Addin> {
} }
unsafe extern "system" fn set_locale<T: Addin>(component: &mut LocaleBase<T>, loc: *const u16) { unsafe extern "system" fn set_locale<T: Addin>(component: &mut LocaleBase<T>, loc: *const u16) {
let len = strlen(loc); let loc = get_str(loc);
let loc = from_raw_parts(loc, len);
component.addin.set_locale(loc) component.addin.set_locale(loc)
} }
@ -570,8 +571,7 @@ unsafe extern "system" fn set_user_interface_language_code<T: Addin>(
component: &mut UserLanguageBase<T>, component: &mut UserLanguageBase<T>,
lang: *const u16, lang: *const u16,
) { ) {
let len = strlen(lang); let lang = get_str(lang);
let lang = from_raw_parts(lang, len);
component.addin.set_user_interface_language_code(lang) component.addin.set_user_interface_language_code(lang)
} }
@ -588,30 +588,27 @@ struct ComponentBase<T: Addin> {
} }
unsafe extern "system" fn destroy<T: Addin>(component: *mut *mut ComponentBase<T>) { unsafe extern "system" fn destroy<T: Addin>(component: *mut *mut ComponentBase<T>) {
let component = unsafe { Box::from_raw(*component) }; let comp = Box::from_raw(*component);
drop(component); drop(comp);
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
struct InitDoneBase<T: Addin> { struct InitDoneBase<T: Addin> {
_vptr1: Box<InitDoneBaseVTable<T>>, _vptr1: usize,
_vptr2: Box<LanguageExtenderBaseVTable<T>>, _vptr2: usize,
_vptr3: Box<LocaleBaseVTable<T>>, _vptr3: usize,
_vptr4: Box<UserLanguageBaseVTable<T>>, _vptr4: usize,
destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>), destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>),
memory: Option<&'static MemoryManager>, memory: Option<&'static MemoryManager>,
addin: T, addin: T,
} }
// type InitDoneBase<T> = ComponentBase<T>;
#[repr(C)] #[repr(C)]
#[allow(dead_code)] #[allow(dead_code)]
struct LanguageExtenderBase<T: Addin> { struct LanguageExtenderBase<T: Addin> {
_vptr2: Box<LanguageExtenderBaseVTable<T>>, _vptr2: usize,
_vptr3: Box<LocaleBaseVTable<T>>, _vptr3: usize,
_vptr4: Box<UserLanguageBaseVTable<T>>, _vptr4: usize,
destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>), destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>),
memory: Option<&'static MemoryManager>, memory: Option<&'static MemoryManager>,
addin: T, addin: T,
@ -620,8 +617,8 @@ struct LanguageExtenderBase<T: Addin> {
#[repr(C)] #[repr(C)]
#[allow(dead_code)] #[allow(dead_code)]
struct LocaleBase<T: Addin> { struct LocaleBase<T: Addin> {
_vptr3: Box<LocaleBaseVTable<T>>, _vptr3: usize,
_vptr4: Box<UserLanguageBaseVTable<T>>, _vptr4: usize,
destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>), destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>),
memory: Option<&'static MemoryManager>, memory: Option<&'static MemoryManager>,
addin: T, addin: T,
@ -630,13 +627,13 @@ struct LocaleBase<T: Addin> {
#[repr(C)] #[repr(C)]
#[allow(dead_code)] #[allow(dead_code)]
struct UserLanguageBase<T: Addin> { struct UserLanguageBase<T: Addin> {
_vptr4: Box<UserLanguageBaseVTable<T>>, _vptr4: usize,
destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>), destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>),
memory: Option<&'static MemoryManager>, memory: Option<&'static MemoryManager>,
addin: T, addin: T,
} }
pub fn create_component<T: Addin>(addin: T) -> *mut c_void { pub unsafe fn create_component<T: Addin>(component: *mut *mut c_void, addin: T) -> c_long {
let vptr1 = Box::new(InitDoneBaseVTable { let vptr1 = Box::new(InitDoneBaseVTable {
dtor: 0, dtor: 0,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
@ -693,26 +690,26 @@ pub fn create_component<T: Addin>(addin: T) -> *mut c_void {
addin, addin,
}); });
let p = Box::leak(c); *component = Box::into_raw(c) as *mut c_void;
p as *mut ComponentBase<T> as *mut c_void 1
} }
pub fn destroy_component(component: *mut *mut c_void) { pub unsafe fn destroy_component(component: *mut *mut c_void) -> c_long {
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
struct ComponentWrapper { struct ComponentWrapper {
vptr1: Box<c_void>, vptr1: usize,
vptr2: Box<c_void>, vptr2: usize,
vptr3: Box<c_void>, vptr3: usize,
vptr4: Box<c_void>, vptr4: usize,
destroy: unsafe extern "system" fn(*mut *mut c_void), destroy: unsafe extern "system" fn(*mut *mut c_void),
} }
unsafe { let wrapper = *component as *mut ComponentWrapper;
let wrapper = *component as *mut ComponentWrapper; let wrapper = &mut *wrapper;
let wrapper = &mut *wrapper; (wrapper.destroy)(component);
(wrapper.destroy)(component); *component = ptr::null_mut();
}
0
} }
#[repr(C)] #[repr(C)]
@ -759,11 +756,16 @@ pub struct Connection {
vptr1: &'static ConnectionVTable, vptr1: &'static ConnectionVTable,
} }
fn strlen(s: *const u16) -> usize { unsafe fn get_str<'a>(s: *const u16) -> &'a [u16] {
let mut i = 0; unsafe fn strlen(s: *const u16) -> usize {
while unsafe { *s.add(i) } != 0 { let mut i = 0;
while unsafe { *s.add(i) } != 0 {
i += 1;
}
i += 1; i += 1;
i
} }
i += 1;
i let len = strlen(s);
from_raw_parts(s, len)
} }

View File

@ -1,8 +1,9 @@
mod addin1; mod addin1;
mod addin2;
mod ffi; mod ffi;
use std::{ use std::{
ffi::{c_long, c_void, c_int}, ffi::{c_int, c_long, c_void},
sync::atomic::{AtomicI32, Ordering}, sync::atomic::{AtomicI32, Ordering},
}; };
@ -10,36 +11,42 @@ use addin1::Addin1;
use ffi::{destroy_component, AttachType}; use ffi::{destroy_component, AttachType};
use utf16_lit::utf16_null; use utf16_lit::utf16_null;
use crate::ffi::create_component; use crate::{addin2::Addin2, ffi::create_component};
pub static mut PLATFORM_CAPABILITIES: AtomicI32 = AtomicI32::new(-1); pub static mut PLATFORM_CAPABILITIES: AtomicI32 = AtomicI32::new(-1);
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[no_mangle] #[no_mangle]
pub extern "C" fn GetClassObject(_name: *const u16, component: *mut *mut c_void) -> c_long { pub unsafe extern "C" fn GetClassObject(name: *const u16, component: *mut *mut c_void) -> c_long {
let addin = Addin1::new(); match *name as u8 {
unsafe { b'1' => {
*component = create_component(addin); let addin = Addin1::new();
create_component(component, addin)
}
b'2' => {
let addin = Addin2::new();
create_component(component, addin)
}
_ => 0,
} }
1
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[no_mangle] #[no_mangle]
pub extern "C" fn DestroyObject(component: *mut *mut c_void) -> c_long { pub unsafe extern "C" fn DestroyObject(component: *mut *mut c_void) -> c_long {
destroy_component(component); destroy_component(component)
0
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[no_mangle] #[no_mangle]
pub extern "C" fn GetClassNames() -> *const u16 { pub extern "C" fn GetClassNames() -> *const u16 {
utf16_null!("Class1").as_ptr() // small strings for performance
utf16_null!("1|2").as_ptr()
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[no_mangle] #[no_mangle]
pub extern "C" fn SetPlatformCapabilities(capabilities: c_int) -> c_long { pub extern "C" fn SetPlatformCapabilities(capabilities: c_int) -> c_int {
unsafe { unsafe {
PLATFORM_CAPABILITIES.store(capabilities, Ordering::Relaxed); PLATFORM_CAPABILITIES.store(capabilities, Ordering::Relaxed);
} }