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

переделал работу в vtable

This commit is contained in:
medigor
2022-12-11 21:45:46 +03:00
parent fd038b3084
commit 6c591c08f8
3 changed files with 93 additions and 147 deletions

View File

@ -54,10 +54,11 @@
При разработке использовался rust 1.65. При разработке использовался rust 1.65.
## Поддержка платформ ## Поддержка платформ
У меня в проде не используется, используйте на свой страх и риск!
- Windows x64 - тестировал, работает и gnu и msvc. - Windows x64 - тестировал, работает и gnu и msvc.
- Windows x32 - работает плохо, или вообще не работает, пока не понял в чем проблема. - Windows x32 - тестировал, работает и gnu и msvc.
- Linux x64 - тестировал, работает. - Linux x64 - тестировал, работает.
- Linux x32 - не тестировал, возможно есть проблемы как в Windows x32. - Linux x32 - не тестировал, думаю что должно работать.
- MacOS - не тестировал, думаю должно работать, т.к. работает Linux x64. - MacOS - не тестировал, думаю должно работать, т.к. работает Linux x64.
- Android/iOS/веб-клиент - не реализовано и планов таких нет. - Android/iOS/веб-клиент - не реализовано и планов таких нет.

View File

@ -26,12 +26,12 @@ pub struct Addin1 {
impl Addin1 { impl Addin1 {
pub fn new() -> Addin1 { pub fn new() -> Addin1 {
Addin1 { Addin1 {
test: 12345, test: 11111,
prop_i32: 0, prop_i32: 22222,
prop_f64: 0.0, prop_f64: 333.33,
prop_bool: false, prop_bool: false,
prop_date: Tm::default(), prop_date: Tm::default(),
prop_str: String::new(), prop_str: String::from("00000"),
prop_blob: Vec::new(), prop_blob: Vec::new(),
} }
} }
@ -78,7 +78,7 @@ impl Addin for Addin1 {
6 => { 6 => {
val.set_blob(self.prop_blob.as_slice()); val.set_blob(self.prop_blob.as_slice());
} }
_ => (), _ => return false,
}; };
true true
} }

View File

@ -14,7 +14,6 @@ pub enum AttachType {
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
#[derive(Clone, Copy, Default)] #[derive(Clone, Copy, Default)]
pub struct Tm { pub struct Tm {
pub sec: c_int, // seconds after the minute - [0, 60] including leap second 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 pub zone: std::ffi::c_char, // timezone abbreviation
} }
#[allow(dead_code)]
pub struct ReturnValue<'a> { pub struct ReturnValue<'a> {
mem: &'a MemoryManager, mem: &'a MemoryManager,
variant: &'a mut TVariant, variant: &'a mut TVariant,
@ -184,7 +182,6 @@ enum VariantType {
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct DataStr { struct DataStr {
pub ptr: *mut u16, pub ptr: *mut u16,
@ -192,7 +189,6 @@ struct DataStr {
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct DataBlob { struct DataBlob {
pub ptr: *mut u8, pub ptr: *mut u8,
@ -210,7 +206,6 @@ union VariantValue {
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
struct TVariant { struct TVariant {
value: VariantValue, value: VariantValue,
elements: u32, //Dimension for an one-dimensional array in pvarVal elements: u32, //Dimension for an one-dimensional array in pvarVal
@ -251,79 +246,80 @@ pub trait Addin {
} }
#[repr(C)] #[repr(C)]
//#[allow(dead_code)] struct This<const OFFSET: usize, T: Addin> {
ptr: *mut Component<T>,
}
impl<'a, const OFFSET: usize, T: Addin> This<OFFSET, T> {
unsafe fn get_component(&mut self) -> &'a mut Component<T> {
let new_ptr = (self as *mut This<OFFSET, T> as *mut c_void)
.sub(OFFSET * std::mem::size_of::<usize>());
&mut *(new_ptr as *mut Component<T>)
}
}
#[repr(C)]
struct InitDoneBaseVTable<T: Addin> { struct InitDoneBaseVTable<T: Addin> {
dtor: usize, dtor: usize,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
dtor2: usize, dtor2: usize,
init: unsafe extern "system" fn(&mut InitDoneBase<T>, &'static Connection) -> bool, init: unsafe extern "system" fn(&mut This<0, T>, &'static Connection) -> bool,
set_mem_manager: set_mem_manager: unsafe extern "system" fn(&mut This<0, T>, &'static MemoryManager) -> bool,
unsafe extern "system" fn(&mut InitDoneBase<T>, &'static MemoryManager) -> bool, get_info: unsafe extern "system" fn(&mut This<0, T>) -> c_long,
get_info: unsafe extern "system" fn(&mut InitDoneBase<T>) -> c_long, done: unsafe extern "system" fn(&mut This<0, T>),
done: unsafe extern "system" fn(&mut InitDoneBase<T>),
} }
unsafe extern "system" fn init<T: Addin>( unsafe extern "system" fn init<T: Addin>(
component: &mut InitDoneBase<T>, this: &mut This<0, T>,
interface: &'static Connection, interface: &'static Connection,
) -> bool { ) -> bool {
let component = this.get_component();
component.addin.init(interface) component.addin.init(interface)
} }
unsafe extern "system" fn set_mem_manager<T: Addin>( unsafe extern "system" fn set_mem_manager<T: Addin>(
component: &mut InitDoneBase<T>, this: &mut This<0, T>,
mem: &'static MemoryManager, mem: &'static MemoryManager,
) -> bool { ) -> bool {
let component = this.get_component();
component.memory = Some(mem); component.memory = Some(mem);
true true
} }
unsafe extern "system" fn get_info<T: Addin>(component: &mut InitDoneBase<T>) -> c_long { unsafe extern "system" fn get_info<T: Addin>(this: &mut This<0, T>) -> c_long {
let component = this.get_component();
component.addin.get_info() as c_long component.addin.get_info() as c_long
} }
unsafe extern "system" fn done<T: Addin>(component: &mut InitDoneBase<T>) { unsafe extern "system" fn done<T: Addin>(this: &mut This<0, T>) {
let component = this.get_component();
component.addin.done() component.addin.done()
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
struct LanguageExtenderBaseVTable<T: Addin> { struct LanguageExtenderBaseVTable<T: Addin> {
dtor: usize, dtor: usize,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
dtor2: usize, dtor2: usize,
register_extension_as: register_extension_as: unsafe extern "system" fn(&mut This<1, T>, *mut *mut u16) -> bool,
unsafe extern "system" fn(&mut LanguageExtenderBase<T>, *mut *mut u16) -> bool, get_n_props: unsafe extern "system" fn(&mut This<1, T>) -> c_long,
get_n_props: unsafe extern "system" fn(&mut LanguageExtenderBase<T>) -> c_long, find_prop: unsafe extern "system" fn(&mut This<1, T>, *const u16) -> c_long,
find_prop: unsafe extern "system" fn(&mut LanguageExtenderBase<T>, *const u16) -> c_long, get_prop_name: unsafe extern "system" fn(&mut This<1, T>, c_long, c_long) -> *const u16,
get_prop_name: get_prop_val: unsafe extern "system" fn(&mut This<1, T>, c_long, &mut TVariant) -> bool,
unsafe extern "system" fn(&mut LanguageExtenderBase<T>, c_long, c_long) -> *const u16, set_prop_val: unsafe extern "system" fn(&mut This<1, T>, c_long, &TVariant) -> bool,
get_prop_val: is_prop_readable: unsafe extern "system" fn(&mut This<1, T>, c_long) -> bool,
unsafe extern "system" fn(&mut LanguageExtenderBase<T>, c_long, &mut TVariant) -> bool, is_prop_writable: unsafe extern "system" fn(&mut This<1, T>, c_long) -> bool,
set_prop_val: get_n_methods: unsafe extern "system" fn(&mut This<1, T>) -> c_long,
unsafe extern "system" fn(&mut LanguageExtenderBase<T>, c_long, &TVariant) -> bool, find_method: unsafe extern "system" fn(&mut This<1, T>, *const u16) -> c_long,
is_prop_readable: unsafe extern "system" fn(&mut LanguageExtenderBase<T>, c_long) -> bool, get_method_name: unsafe extern "system" fn(&mut This<1, T>, c_long, c_long) -> *const u16,
is_prop_writable: unsafe extern "system" fn(&mut LanguageExtenderBase<T>, c_long) -> bool, get_n_params: unsafe extern "system" fn(&mut This<1, T>, c_long) -> c_long,
get_n_methods: unsafe extern "system" fn(&mut LanguageExtenderBase<T>) -> c_long, get_param_def_value:
find_method: unsafe extern "system" fn(&mut LanguageExtenderBase<T>, *const u16) -> c_long, unsafe extern "system" fn(&mut This<1, T>, c_long, c_long, &mut TVariant) -> bool,
get_method_name: has_ret_val: unsafe extern "system" fn(&mut This<1, T>, c_long) -> bool,
unsafe extern "system" fn(&mut LanguageExtenderBase<T>, c_long, c_long) -> *const u16, call_as_proc:
get_n_params: unsafe extern "system" fn(&mut LanguageExtenderBase<T>, c_long) -> c_long, unsafe extern "system" fn(&mut This<1, T>, c_long, *const TVariant, c_long) -> bool,
get_param_def_value: unsafe extern "system" fn(
&mut LanguageExtenderBase<T>,
c_long,
c_long,
&mut TVariant,
) -> bool,
has_ret_val: unsafe extern "system" fn(&mut LanguageExtenderBase<T>, c_long) -> bool,
call_as_proc: unsafe extern "system" fn(
&mut LanguageExtenderBase<T>,
c_long,
*const TVariant,
c_long,
) -> bool,
call_as_func: unsafe extern "system" fn( call_as_func: unsafe extern "system" fn(
&mut LanguageExtenderBase<T>, &mut This<1, T>,
c_long, c_long,
&mut TVariant, &mut TVariant,
*const TVariant, *const TVariant,
@ -332,9 +328,10 @@ struct LanguageExtenderBaseVTable<T: Addin> {
} }
unsafe extern "system" fn register_extension_as<T: Addin>( unsafe extern "system" fn register_extension_as<T: Addin>(
component: &mut LanguageExtenderBase<T>, this: &mut This<1, T>,
name: *mut *mut u16, name: *mut *mut u16,
) -> bool { ) -> bool {
let component = this.get_component();
let Some(allocator) = component.memory else { let Some(allocator) = component.memory else {
return false; return false;
}; };
@ -350,14 +347,13 @@ unsafe extern "system" fn register_extension_as<T: Addin>(
true true
} }
unsafe extern "system" fn get_n_props<T: Addin>(component: &mut LanguageExtenderBase<T>) -> c_long { unsafe extern "system" fn get_n_props<T: Addin>(this: &mut This<1, T>) -> c_long {
let component = this.get_component();
component.addin.get_n_props() as c_long component.addin.get_n_props() as c_long
} }
unsafe extern "system" fn find_prop<T: Addin>( unsafe extern "system" fn find_prop<T: Addin>(this: &mut This<1, T>, name: *const u16) -> c_long {
component: &mut LanguageExtenderBase<T>, let component = this.get_component();
name: *const u16,
) -> c_long {
let name = get_str(name); let name = get_str(name);
match component.addin.find_prop(name) { match component.addin.find_prop(name) {
Some(i) => i as c_long, Some(i) => i as c_long,
@ -366,10 +362,11 @@ unsafe extern "system" fn find_prop<T: Addin>(
} }
unsafe extern "system" fn get_prop_name<T: Addin>( unsafe extern "system" fn get_prop_name<T: Addin>(
component: &mut LanguageExtenderBase<T>, this: &mut This<1, T>,
num: c_long, num: c_long,
alias: c_long, alias: c_long,
) -> *const u16 { ) -> *const u16 {
let component = this.get_component();
let Some(allocator) = component.memory else { let Some(allocator) = component.memory else {
return ptr::null(); return ptr::null();
}; };
@ -385,10 +382,11 @@ unsafe extern "system" fn get_prop_name<T: Addin>(
} }
unsafe extern "system" fn get_prop_val<T: Addin>( unsafe extern "system" fn get_prop_val<T: Addin>(
component: &mut LanguageExtenderBase<T>, component: &mut This<1, T>,
num: c_long, num: c_long,
val: &mut TVariant, val: &mut TVariant,
) -> bool { ) -> bool {
let component = component.get_component();
let Some(mem) = component.memory else { let Some(mem) = component.memory else {
return false; return false;
}; };
@ -403,38 +401,32 @@ unsafe extern "system" fn get_prop_val<T: Addin>(
} }
unsafe extern "system" fn set_prop_val<T: Addin>( unsafe extern "system" fn set_prop_val<T: Addin>(
component: &mut LanguageExtenderBase<T>, this: &mut This<1, T>,
num: c_long, num: c_long,
val: &TVariant, val: &TVariant,
) -> bool { ) -> bool {
let component = this.get_component();
let param = ParamValue::from(val); let param = ParamValue::from(val);
component.addin.set_prop_val(num as usize, &param) component.addin.set_prop_val(num as usize, &param)
} }
unsafe extern "system" fn is_prop_readable<T: Addin>( unsafe extern "system" fn is_prop_readable<T: Addin>(this: &mut This<1, T>, num: c_long) -> bool {
component: &mut LanguageExtenderBase<T>, let component = this.get_component();
num: c_long,
) -> bool {
component.addin.is_prop_readable(num as usize) component.addin.is_prop_readable(num as usize)
} }
unsafe extern "system" fn is_prop_writable<T: Addin>( unsafe extern "system" fn is_prop_writable<T: Addin>(this: &mut This<1, T>, num: c_long) -> bool {
component: &mut LanguageExtenderBase<T>, let component = this.get_component();
num: c_long,
) -> bool {
component.addin.is_prop_writable(num as usize) component.addin.is_prop_writable(num as usize)
} }
unsafe extern "system" fn get_n_methods<T: Addin>( unsafe extern "system" fn get_n_methods<T: Addin>(this: &mut This<1, T>) -> c_long {
component: &mut LanguageExtenderBase<T>, let component = this.get_component();
) -> c_long {
component.addin.get_n_methods() as c_long component.addin.get_n_methods() as c_long
} }
unsafe extern "system" fn find_method<T: Addin>( unsafe extern "system" fn find_method<T: Addin>(this: &mut This<1, T>, name: *const u16) -> c_long {
component: &mut LanguageExtenderBase<T>, let component = this.get_component();
name: *const u16,
) -> c_long {
let name = get_str(name); let name = get_str(name);
match component.addin.find_method(name) { match component.addin.find_method(name) {
Some(i) => i as c_long, Some(i) => i as c_long,
@ -443,10 +435,11 @@ unsafe extern "system" fn find_method<T: Addin>(
} }
unsafe extern "system" fn get_method_name<T: Addin>( unsafe extern "system" fn get_method_name<T: Addin>(
component: &mut LanguageExtenderBase<T>, this: &mut This<1, T>,
num: c_long, num: c_long,
alias: c_long, alias: c_long,
) -> *const u16 { ) -> *const u16 {
let component = this.get_component();
let Some(allocator) = component.memory else { let Some(allocator) = component.memory else {
return ptr::null(); return ptr::null();
}; };
@ -461,19 +454,18 @@ unsafe extern "system" fn get_method_name<T: Addin>(
name.as_ptr() name.as_ptr()
} }
unsafe extern "system" fn get_n_params<T: Addin>( unsafe extern "system" fn get_n_params<T: Addin>(this: &mut This<1, T>, num: c_long) -> c_long {
component: &mut LanguageExtenderBase<T>, let component = this.get_component();
num: c_long,
) -> c_long {
component.addin.get_n_params(num as usize) as c_long component.addin.get_n_params(num as usize) as c_long
} }
unsafe extern "system" fn get_param_def_value<T: Addin>( unsafe extern "system" fn get_param_def_value<T: Addin>(
component: &mut LanguageExtenderBase<T>, this: &mut This<1, T>,
method_num: c_long, method_num: c_long,
param_num: c_long, param_num: c_long,
val: &mut TVariant, val: &mut TVariant,
) -> bool { ) -> bool {
let component = this.get_component();
let Some(mem) = component.memory else { let Some(mem) = component.memory else {
return false; return false;
}; };
@ -491,19 +483,18 @@ unsafe extern "system" fn get_param_def_value<T: Addin>(
&& result && result
} }
unsafe extern "system" fn has_ret_val<T: Addin>( unsafe extern "system" fn has_ret_val<T: Addin>(this: &mut This<1, T>, method_num: c_long) -> bool {
component: &mut LanguageExtenderBase<T>, let component = this.get_component();
method_num: c_long,
) -> bool {
component.addin.has_ret_val(method_num as usize) component.addin.has_ret_val(method_num as usize)
} }
unsafe extern "system" fn call_as_proc<T: Addin>( unsafe extern "system" fn call_as_proc<T: Addin>(
component: &mut LanguageExtenderBase<T>, this: &mut This<1, T>,
method_num: c_long, method_num: c_long,
params: *const TVariant, params: *const TVariant,
size_array: c_long, size_array: c_long,
) -> bool { ) -> bool {
let component = this.get_component();
let param_values = from_raw_parts(params, size_array as usize) let param_values = from_raw_parts(params, size_array as usize)
.iter() .iter()
.map(|x| ParamValue::from(x)) .map(|x| ParamValue::from(x))
@ -515,12 +506,13 @@ unsafe extern "system" fn call_as_proc<T: Addin>(
} }
unsafe extern "system" fn call_as_func<T: Addin>( unsafe extern "system" fn call_as_func<T: Addin>(
component: &mut LanguageExtenderBase<T>, this: &mut This<1, T>,
method_num: c_long, method_num: c_long,
ret_value: &mut TVariant, ret_value: &mut TVariant,
params: *const TVariant, params: *const TVariant,
size_array: c_long, size_array: c_long,
) -> bool { ) -> bool {
let component = this.get_component();
let Some(mem) = component.memory else { let Some(mem) = component.memory else {
return false; return false;
}; };
@ -544,95 +536,52 @@ unsafe extern "system" fn call_as_func<T: Addin>(
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
struct LocaleBaseVTable<T: Addin> { struct LocaleBaseVTable<T: Addin> {
dtor: usize, dtor: usize,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
dtor2: usize, dtor2: usize,
set_locale: unsafe extern "system" fn(&mut LocaleBase<T>, *const u16), set_locale: unsafe extern "system" fn(&mut This<2, T>, *const u16),
} }
unsafe extern "system" fn set_locale<T: Addin>(component: &mut LocaleBase<T>, loc: *const u16) { unsafe extern "system" fn set_locale<T: Addin>(this: &mut This<2, T>, loc: *const u16) {
let component = this.get_component();
let loc = get_str(loc); let loc = get_str(loc);
component.addin.set_locale(loc) component.addin.set_locale(loc)
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
struct UserLanguageBaseVTable<T: Addin> { struct UserLanguageBaseVTable<T: Addin> {
dtor: usize, dtor: usize,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
dtor2: usize, dtor2: usize,
set_user_interface_language_code: set_user_interface_language_code: unsafe extern "system" fn(&mut This<3, T>, *const u16),
unsafe extern "system" fn(&mut UserLanguageBase<T>, *const u16),
} }
unsafe extern "system" fn set_user_interface_language_code<T: Addin>( unsafe extern "system" fn set_user_interface_language_code<T: Addin>(
component: &mut UserLanguageBase<T>, this: &mut This<3, T>,
lang: *const u16, lang: *const u16,
) { ) {
let component = this.get_component();
let lang = get_str(lang); let lang = get_str(lang);
component.addin.set_user_interface_language_code(lang) component.addin.set_user_interface_language_code(lang)
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)] struct Component<T: Addin> {
struct ComponentBase<T: Addin> {
vptr1: Box<InitDoneBaseVTable<T>>, vptr1: Box<InitDoneBaseVTable<T>>,
vptr2: Box<LanguageExtenderBaseVTable<T>>, vptr2: Box<LanguageExtenderBaseVTable<T>>,
vptr3: Box<LocaleBaseVTable<T>>, vptr3: Box<LocaleBaseVTable<T>>,
vptr4: Box<UserLanguageBaseVTable<T>>, vptr4: Box<UserLanguageBaseVTable<T>>,
destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>), destroy: unsafe extern "system" fn(*mut *mut Component<T>),
memory: Option<&'static MemoryManager>, memory: Option<&'static MemoryManager>,
addin: T, addin: T,
} }
unsafe extern "system" fn destroy<T: Addin>(component: *mut *mut ComponentBase<T>) { unsafe extern "system" fn destroy<T: Addin>(component: *mut *mut Component<T>) {
let comp = Box::from_raw(*component); let comp = Box::from_raw(*component);
drop(comp); drop(comp);
} }
#[repr(C)]
struct InitDoneBase<T: Addin> {
_vptr1: usize,
_vptr2: usize,
_vptr3: usize,
_vptr4: usize,
destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>),
memory: Option<&'static MemoryManager>,
addin: T,
}
#[repr(C)]
#[allow(dead_code)]
struct LanguageExtenderBase<T: Addin> {
_vptr2: usize,
_vptr3: usize,
_vptr4: usize,
destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>),
memory: Option<&'static MemoryManager>,
addin: T,
}
#[repr(C)]
#[allow(dead_code)]
struct LocaleBase<T: Addin> {
_vptr3: usize,
_vptr4: usize,
destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>),
memory: Option<&'static MemoryManager>,
addin: T,
}
#[repr(C)]
#[allow(dead_code)]
struct UserLanguageBase<T: Addin> {
_vptr4: usize,
destroy: unsafe extern "system" fn(*mut *mut ComponentBase<T>),
memory: Option<&'static MemoryManager>,
addin: T,
}
pub unsafe fn create_component<T: Addin>(component: *mut *mut c_void, addin: T) -> c_long { 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,
@ -680,7 +629,7 @@ pub unsafe fn create_component<T: Addin>(component: *mut *mut c_void, addin: T)
set_user_interface_language_code, set_user_interface_language_code,
}); });
let c = Box::new(ComponentBase { let c = Box::new(Component {
vptr1, vptr1,
vptr2, vptr2,
vptr3, vptr3,
@ -713,7 +662,6 @@ pub unsafe fn destroy_component(component: *mut *mut c_void) -> c_long {
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
struct MemoryManagerVTable { struct MemoryManagerVTable {
dtor: usize, dtor: usize,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
@ -723,7 +671,6 @@ struct MemoryManagerVTable {
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
struct MemoryManager { struct MemoryManager {
vptr1: &'static MemoryManagerVTable, vptr1: &'static MemoryManagerVTable,
} }
@ -743,7 +690,6 @@ impl MemoryManager {
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
struct ConnectionVTable { struct ConnectionVTable {
dtor: usize, dtor: usize,
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
@ -751,7 +697,6 @@ struct ConnectionVTable {
} }
#[repr(C)] #[repr(C)]
#[allow(dead_code)]
pub struct Connection { pub struct Connection {
vptr1: &'static ConnectionVTable, vptr1: &'static ConnectionVTable,
} }