From 6c591c08f89ae3340c52ba23055bc5346091efbd Mon Sep 17 00:00:00 2001 From: medigor Date: Sun, 11 Dec 2022 21:45:46 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B0=D0=BB=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=83=20=D0=B2=20?= =?UTF-8?q?vtable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +- src/addin1.rs | 10 +-- src/ffi.rs | 225 +++++++++++++++++++------------------------------- 3 files changed, 93 insertions(+), 147 deletions(-) diff --git a/README.md b/README.md index 494cfba..4cf3c0f 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,11 @@ При разработке использовался rust 1.65. ## Поддержка платформ +У меня в проде не используется, используйте на свой страх и риск! - Windows x64 - тестировал, работает и gnu и msvc. -- Windows x32 - работает плохо, или вообще не работает, пока не понял в чем проблема. +- Windows x32 - тестировал, работает и gnu и msvc. - Linux x64 - тестировал, работает. -- Linux x32 - не тестировал, возможно есть проблемы как в Windows x32. +- Linux x32 - не тестировал, думаю что должно работать. - MacOS - не тестировал, думаю должно работать, т.к. работает Linux x64. - Android/iOS/веб-клиент - не реализовано и планов таких нет. diff --git a/src/addin1.rs b/src/addin1.rs index b7ce016..260e902 100644 --- a/src/addin1.rs +++ b/src/addin1.rs @@ -26,12 +26,12 @@ pub struct Addin1 { impl Addin1 { pub fn new() -> Addin1 { Addin1 { - test: 12345, - prop_i32: 0, - prop_f64: 0.0, + test: 11111, + prop_i32: 22222, + prop_f64: 333.33, prop_bool: false, prop_date: Tm::default(), - prop_str: String::new(), + prop_str: String::from("00000"), prop_blob: Vec::new(), } } @@ -78,7 +78,7 @@ impl Addin for Addin1 { 6 => { val.set_blob(self.prop_blob.as_slice()); } - _ => (), + _ => return false, }; true } diff --git a/src/ffi.rs b/src/ffi.rs index 4d6ede7..c05735f 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -14,7 +14,6 @@ pub enum AttachType { } #[repr(C)] -#[allow(dead_code)] #[derive(Clone, Copy, Default)] pub struct Tm { pub sec: c_int, // seconds after the minute - [0, 60] including leap second @@ -33,7 +32,6 @@ pub struct Tm { pub zone: std::ffi::c_char, // timezone abbreviation } -#[allow(dead_code)] pub struct ReturnValue<'a> { mem: &'a MemoryManager, variant: &'a mut TVariant, @@ -184,7 +182,6 @@ enum VariantType { } #[repr(C)] -#[allow(dead_code)] #[derive(Clone, Copy)] struct DataStr { pub ptr: *mut u16, @@ -192,7 +189,6 @@ struct DataStr { } #[repr(C)] -#[allow(dead_code)] #[derive(Clone, Copy)] struct DataBlob { pub ptr: *mut u8, @@ -210,7 +206,6 @@ union VariantValue { } #[repr(C)] -#[allow(dead_code)] struct TVariant { value: VariantValue, elements: u32, //Dimension for an one-dimensional array in pvarVal @@ -251,79 +246,80 @@ pub trait Addin { } #[repr(C)] -//#[allow(dead_code)] +struct This { + ptr: *mut Component, +} + +impl<'a, const OFFSET: usize, T: Addin> This { + unsafe fn get_component(&mut self) -> &'a mut Component { + let new_ptr = (self as *mut This as *mut c_void) + .sub(OFFSET * std::mem::size_of::()); + &mut *(new_ptr as *mut Component) + } +} + +#[repr(C)] struct InitDoneBaseVTable { dtor: usize, #[cfg(target_family = "unix")] dtor2: usize, - init: unsafe extern "system" fn(&mut InitDoneBase, &'static Connection) -> bool, - set_mem_manager: - unsafe extern "system" fn(&mut InitDoneBase, &'static MemoryManager) -> bool, - get_info: unsafe extern "system" fn(&mut InitDoneBase) -> c_long, - done: unsafe extern "system" fn(&mut InitDoneBase), + init: unsafe extern "system" fn(&mut This<0, T>, &'static Connection) -> bool, + set_mem_manager: unsafe extern "system" fn(&mut This<0, T>, &'static MemoryManager) -> bool, + get_info: unsafe extern "system" fn(&mut This<0, T>) -> c_long, + done: unsafe extern "system" fn(&mut This<0, T>), } unsafe extern "system" fn init( - component: &mut InitDoneBase, + this: &mut This<0, T>, interface: &'static Connection, ) -> bool { + let component = this.get_component(); component.addin.init(interface) } unsafe extern "system" fn set_mem_manager( - component: &mut InitDoneBase, + this: &mut This<0, T>, mem: &'static MemoryManager, ) -> bool { + let component = this.get_component(); component.memory = Some(mem); true } -unsafe extern "system" fn get_info(component: &mut InitDoneBase) -> c_long { +unsafe extern "system" fn get_info(this: &mut This<0, T>) -> c_long { + let component = this.get_component(); component.addin.get_info() as c_long } -unsafe extern "system" fn done(component: &mut InitDoneBase) { +unsafe extern "system" fn done(this: &mut This<0, T>) { + let component = this.get_component(); component.addin.done() } #[repr(C)] -#[allow(dead_code)] struct LanguageExtenderBaseVTable { dtor: usize, #[cfg(target_family = "unix")] dtor2: usize, - register_extension_as: - unsafe extern "system" fn(&mut LanguageExtenderBase, *mut *mut u16) -> bool, - get_n_props: unsafe extern "system" fn(&mut LanguageExtenderBase) -> c_long, - find_prop: unsafe extern "system" fn(&mut LanguageExtenderBase, *const u16) -> c_long, - get_prop_name: - unsafe extern "system" fn(&mut LanguageExtenderBase, c_long, c_long) -> *const u16, - get_prop_val: - unsafe extern "system" fn(&mut LanguageExtenderBase, c_long, &mut TVariant) -> bool, - set_prop_val: - unsafe extern "system" fn(&mut LanguageExtenderBase, c_long, &TVariant) -> bool, - is_prop_readable: unsafe extern "system" fn(&mut LanguageExtenderBase, c_long) -> bool, - is_prop_writable: unsafe extern "system" fn(&mut LanguageExtenderBase, c_long) -> bool, - get_n_methods: unsafe extern "system" fn(&mut LanguageExtenderBase) -> c_long, - find_method: unsafe extern "system" fn(&mut LanguageExtenderBase, *const u16) -> c_long, - get_method_name: - unsafe extern "system" fn(&mut LanguageExtenderBase, c_long, c_long) -> *const u16, - get_n_params: unsafe extern "system" fn(&mut LanguageExtenderBase, c_long) -> c_long, - get_param_def_value: unsafe extern "system" fn( - &mut LanguageExtenderBase, - c_long, - c_long, - &mut TVariant, - ) -> bool, - has_ret_val: unsafe extern "system" fn(&mut LanguageExtenderBase, c_long) -> bool, - call_as_proc: unsafe extern "system" fn( - &mut LanguageExtenderBase, - c_long, - *const TVariant, - c_long, - ) -> bool, + register_extension_as: unsafe extern "system" fn(&mut This<1, T>, *mut *mut u16) -> bool, + get_n_props: unsafe extern "system" fn(&mut This<1, T>) -> c_long, + find_prop: unsafe extern "system" fn(&mut This<1, T>, *const u16) -> c_long, + get_prop_name: unsafe extern "system" fn(&mut This<1, T>, c_long, c_long) -> *const u16, + get_prop_val: unsafe extern "system" fn(&mut This<1, T>, c_long, &mut TVariant) -> bool, + set_prop_val: unsafe extern "system" fn(&mut This<1, T>, c_long, &TVariant) -> bool, + is_prop_readable: unsafe extern "system" fn(&mut This<1, T>, c_long) -> bool, + is_prop_writable: unsafe extern "system" fn(&mut This<1, T>, c_long) -> bool, + get_n_methods: unsafe extern "system" fn(&mut This<1, T>) -> c_long, + find_method: unsafe extern "system" fn(&mut This<1, T>, *const u16) -> c_long, + get_method_name: unsafe extern "system" fn(&mut This<1, T>, c_long, c_long) -> *const u16, + get_n_params: unsafe extern "system" fn(&mut This<1, T>, c_long) -> c_long, + get_param_def_value: + unsafe extern "system" fn(&mut This<1, T>, c_long, c_long, &mut TVariant) -> bool, + has_ret_val: unsafe extern "system" fn(&mut This<1, T>, c_long) -> bool, + call_as_proc: + unsafe extern "system" fn(&mut This<1, T>, c_long, *const TVariant, c_long) -> bool, call_as_func: unsafe extern "system" fn( - &mut LanguageExtenderBase, + &mut This<1, T>, c_long, &mut TVariant, *const TVariant, @@ -332,9 +328,10 @@ struct LanguageExtenderBaseVTable { } unsafe extern "system" fn register_extension_as( - component: &mut LanguageExtenderBase, + this: &mut This<1, T>, name: *mut *mut u16, ) -> bool { + let component = this.get_component(); let Some(allocator) = component.memory else { return false; }; @@ -350,14 +347,13 @@ unsafe extern "system" fn register_extension_as( true } -unsafe extern "system" fn get_n_props(component: &mut LanguageExtenderBase) -> c_long { +unsafe extern "system" fn get_n_props(this: &mut This<1, T>) -> c_long { + let component = this.get_component(); component.addin.get_n_props() as c_long } -unsafe extern "system" fn find_prop( - component: &mut LanguageExtenderBase, - name: *const u16, -) -> c_long { +unsafe extern "system" fn find_prop(this: &mut This<1, T>, name: *const u16) -> c_long { + let component = this.get_component(); let name = get_str(name); match component.addin.find_prop(name) { Some(i) => i as c_long, @@ -366,10 +362,11 @@ unsafe extern "system" fn find_prop( } unsafe extern "system" fn get_prop_name( - component: &mut LanguageExtenderBase, + this: &mut This<1, T>, num: c_long, alias: c_long, ) -> *const u16 { + let component = this.get_component(); let Some(allocator) = component.memory else { return ptr::null(); }; @@ -385,10 +382,11 @@ unsafe extern "system" fn get_prop_name( } unsafe extern "system" fn get_prop_val( - component: &mut LanguageExtenderBase, + component: &mut This<1, T>, num: c_long, val: &mut TVariant, ) -> bool { + let component = component.get_component(); let Some(mem) = component.memory else { return false; }; @@ -403,38 +401,32 @@ unsafe extern "system" fn get_prop_val( } unsafe extern "system" fn set_prop_val( - component: &mut LanguageExtenderBase, + this: &mut This<1, T>, num: c_long, val: &TVariant, ) -> bool { + let component = this.get_component(); let param = ParamValue::from(val); component.addin.set_prop_val(num as usize, ¶m) } -unsafe extern "system" fn is_prop_readable( - component: &mut LanguageExtenderBase, - num: c_long, -) -> bool { +unsafe extern "system" fn is_prop_readable(this: &mut This<1, T>, num: c_long) -> bool { + let component = this.get_component(); component.addin.is_prop_readable(num as usize) } -unsafe extern "system" fn is_prop_writable( - component: &mut LanguageExtenderBase, - num: c_long, -) -> bool { +unsafe extern "system" fn is_prop_writable(this: &mut This<1, T>, num: c_long) -> bool { + let component = this.get_component(); component.addin.is_prop_writable(num as usize) } -unsafe extern "system" fn get_n_methods( - component: &mut LanguageExtenderBase, -) -> c_long { +unsafe extern "system" fn get_n_methods(this: &mut This<1, T>) -> c_long { + let component = this.get_component(); component.addin.get_n_methods() as c_long } -unsafe extern "system" fn find_method( - component: &mut LanguageExtenderBase, - name: *const u16, -) -> c_long { +unsafe extern "system" fn find_method(this: &mut This<1, T>, name: *const u16) -> c_long { + let component = this.get_component(); let name = get_str(name); match component.addin.find_method(name) { Some(i) => i as c_long, @@ -443,10 +435,11 @@ unsafe extern "system" fn find_method( } unsafe extern "system" fn get_method_name( - component: &mut LanguageExtenderBase, + this: &mut This<1, T>, num: c_long, alias: c_long, ) -> *const u16 { + let component = this.get_component(); let Some(allocator) = component.memory else { return ptr::null(); }; @@ -461,19 +454,18 @@ unsafe extern "system" fn get_method_name( name.as_ptr() } -unsafe extern "system" fn get_n_params( - component: &mut LanguageExtenderBase, - num: c_long, -) -> c_long { +unsafe extern "system" fn get_n_params(this: &mut This<1, T>, num: c_long) -> c_long { + let component = this.get_component(); component.addin.get_n_params(num as usize) as c_long } unsafe extern "system" fn get_param_def_value( - component: &mut LanguageExtenderBase, + this: &mut This<1, T>, method_num: c_long, param_num: c_long, val: &mut TVariant, ) -> bool { + let component = this.get_component(); let Some(mem) = component.memory else { return false; }; @@ -491,19 +483,18 @@ unsafe extern "system" fn get_param_def_value( && result } -unsafe extern "system" fn has_ret_val( - component: &mut LanguageExtenderBase, - method_num: c_long, -) -> bool { +unsafe extern "system" fn has_ret_val(this: &mut This<1, T>, method_num: c_long) -> bool { + let component = this.get_component(); component.addin.has_ret_val(method_num as usize) } unsafe extern "system" fn call_as_proc( - component: &mut LanguageExtenderBase, + this: &mut This<1, T>, method_num: c_long, params: *const TVariant, size_array: c_long, ) -> bool { + let component = this.get_component(); let param_values = from_raw_parts(params, size_array as usize) .iter() .map(|x| ParamValue::from(x)) @@ -515,12 +506,13 @@ unsafe extern "system" fn call_as_proc( } unsafe extern "system" fn call_as_func( - component: &mut LanguageExtenderBase, + this: &mut This<1, T>, method_num: c_long, ret_value: &mut TVariant, params: *const TVariant, size_array: c_long, ) -> bool { + let component = this.get_component(); let Some(mem) = component.memory else { return false; }; @@ -544,95 +536,52 @@ unsafe extern "system" fn call_as_func( } #[repr(C)] -#[allow(dead_code)] struct LocaleBaseVTable { dtor: usize, #[cfg(target_family = "unix")] dtor2: usize, - set_locale: unsafe extern "system" fn(&mut LocaleBase, *const u16), + set_locale: unsafe extern "system" fn(&mut This<2, T>, *const u16), } -unsafe extern "system" fn set_locale(component: &mut LocaleBase, loc: *const u16) { +unsafe extern "system" fn set_locale(this: &mut This<2, T>, loc: *const u16) { + let component = this.get_component(); let loc = get_str(loc); component.addin.set_locale(loc) } #[repr(C)] -#[allow(dead_code)] struct UserLanguageBaseVTable { dtor: usize, #[cfg(target_family = "unix")] dtor2: usize, - set_user_interface_language_code: - unsafe extern "system" fn(&mut UserLanguageBase, *const u16), + set_user_interface_language_code: unsafe extern "system" fn(&mut This<3, T>, *const u16), } unsafe extern "system" fn set_user_interface_language_code( - component: &mut UserLanguageBase, + this: &mut This<3, T>, lang: *const u16, ) { + let component = this.get_component(); let lang = get_str(lang); component.addin.set_user_interface_language_code(lang) } #[repr(C)] -#[allow(dead_code)] -struct ComponentBase { +struct Component { vptr1: Box>, vptr2: Box>, vptr3: Box>, vptr4: Box>, - destroy: unsafe extern "system" fn(*mut *mut ComponentBase), + destroy: unsafe extern "system" fn(*mut *mut Component), memory: Option<&'static MemoryManager>, addin: T, } -unsafe extern "system" fn destroy(component: *mut *mut ComponentBase) { +unsafe extern "system" fn destroy(component: *mut *mut Component) { let comp = Box::from_raw(*component); drop(comp); } -#[repr(C)] -struct InitDoneBase { - _vptr1: usize, - _vptr2: usize, - _vptr3: usize, - _vptr4: usize, - destroy: unsafe extern "system" fn(*mut *mut ComponentBase), - memory: Option<&'static MemoryManager>, - addin: T, -} - -#[repr(C)] -#[allow(dead_code)] -struct LanguageExtenderBase { - _vptr2: usize, - _vptr3: usize, - _vptr4: usize, - destroy: unsafe extern "system" fn(*mut *mut ComponentBase), - memory: Option<&'static MemoryManager>, - addin: T, -} - -#[repr(C)] -#[allow(dead_code)] -struct LocaleBase { - _vptr3: usize, - _vptr4: usize, - destroy: unsafe extern "system" fn(*mut *mut ComponentBase), - memory: Option<&'static MemoryManager>, - addin: T, -} - -#[repr(C)] -#[allow(dead_code)] -struct UserLanguageBase { - _vptr4: usize, - destroy: unsafe extern "system" fn(*mut *mut ComponentBase), - memory: Option<&'static MemoryManager>, - addin: T, -} - pub unsafe fn create_component(component: *mut *mut c_void, addin: T) -> c_long { let vptr1 = Box::new(InitDoneBaseVTable { dtor: 0, @@ -680,7 +629,7 @@ pub unsafe fn create_component(component: *mut *mut c_void, addin: T) set_user_interface_language_code, }); - let c = Box::new(ComponentBase { + let c = Box::new(Component { vptr1, vptr2, vptr3, @@ -713,7 +662,6 @@ pub unsafe fn destroy_component(component: *mut *mut c_void) -> c_long { } #[repr(C)] -#[allow(dead_code)] struct MemoryManagerVTable { dtor: usize, #[cfg(target_family = "unix")] @@ -723,7 +671,6 @@ struct MemoryManagerVTable { } #[repr(C)] -#[allow(dead_code)] struct MemoryManager { vptr1: &'static MemoryManagerVTable, } @@ -743,7 +690,6 @@ impl MemoryManager { } #[repr(C)] -#[allow(dead_code)] struct ConnectionVTable { dtor: usize, #[cfg(target_family = "unix")] @@ -751,7 +697,6 @@ struct ConnectionVTable { } #[repr(C)] -#[allow(dead_code)] pub struct Connection { vptr1: &'static ConnectionVTable, }