mirror of
https://github.com/medigor/example-native-api-rs.git
synced 2025-06-13 00:07:57 +02:00
out parameters
This commit is contained in:
parent
4dee8a2c43
commit
30cbaccec0
@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ConfigDumpInfo xmlns="http://v8.1c.ru/8.3/xcf/dumpinfo" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" format="Hierarchical" version="2.15">
|
<ConfigDumpInfo xmlns="http://v8.1c.ru/8.3/xcf/dumpinfo" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" format="Hierarchical" version="2.15">
|
||||||
<ConfigVersions>
|
<ConfigVersions>
|
||||||
<Metadata name="Configuration.Конфигурация" id="72b21170-d6cc-48ee-8426-d69353f61fd5" configVersion="a64d3ffe00e3344f821527065fd9669400000000"/>
|
<Metadata name="Configuration.Конфигурация" id="72b21170-d6cc-48ee-8426-d69353f61fd5" configVersion="c712ec3fc94b2b4182496f0827cf4bff00000000"/>
|
||||||
<Metadata name="Configuration.Конфигурация.HomePageWorkArea" id="29e7f5a4-dc26-408a-bd6e-083b5bf1384c.8" configVersion="0169b7c0855a0e459f04d61506e77aef00000000"/>
|
<Metadata name="Configuration.Конфигурация.HomePageWorkArea" id="29e7f5a4-dc26-408a-bd6e-083b5bf1384c.8" configVersion="33c420fc5cc12348954bd259bb0c136000000000"/>
|
||||||
<Metadata name="DataProcessor.Обработка1" id="33179d0b-730e-44f5-b20c-1af11f7f1f60" configVersion="2f45b64f61dc1b4cb42bd668cf3942df00000000"/>
|
<Metadata name="DataProcessor.Обработка1" id="33179d0b-730e-44f5-b20c-1af11f7f1f60" configVersion="86cf80c3e753094aa1ab6bbb3cce13b400000000"/>
|
||||||
<Metadata name="DataProcessor.Обработка1.Form.Форма" id="24033a67-5ef1-4265-9a88-eb7f279ce1cb" configVersion="b173f3c73e1fdd489319ecfd372edab800000000"/>
|
<Metadata name="DataProcessor.Обработка1.Form.Форма" id="24033a67-5ef1-4265-9a88-eb7f279ce1cb" configVersion="b49039a0c3894b41a732cee38bfae78d00000000"/>
|
||||||
<Metadata name="DataProcessor.Обработка1.Form.Форма.Form" id="24033a67-5ef1-4265-9a88-eb7f279ce1cb.0" configVersion="7894c5dc6490f14d92e085d4d4b8847300000000"/>
|
<Metadata name="DataProcessor.Обработка1.Form.Форма.Form" id="24033a67-5ef1-4265-9a88-eb7f279ce1cb.0" configVersion="4773009ef4f1164eadd05bc75928d86900000000"/>
|
||||||
<Metadata name="Language.Русский" id="e3ac9659-5250-4530-9ca6-3f4f4ef6413a" configVersion="0a61ebedb1993c4a9ed758c68a381d7d00000000"/>
|
<Metadata name="Language.Русский" id="e3ac9659-5250-4530-9ca6-3f4f4ef6413a" configVersion="63a64f60c307414fabfabd0d777a47cc00000000"/>
|
||||||
</ConfigVersions>
|
</ConfigVersions>
|
||||||
</ConfigDumpInfo>
|
</ConfigDumpInfo>
|
@ -79,6 +79,14 @@
|
|||||||
ВызватьИсключение "Не удалось установить значение Method1";
|
ВызватьИсключение "Не удалось установить значение Method1";
|
||||||
КонецЕсли;
|
КонецЕсли;
|
||||||
|
|
||||||
|
ВозвращаемаяСтрока = Неопределено;
|
||||||
|
ВозвращаемоеЧисло = Неопределено;
|
||||||
|
Если Не ОбъектКомпоненты.Method2(ВозвращаемаяСтрока, ВозвращаемоеЧисло)
|
||||||
|
Или ВозвращаемаяСтрока <> "Return value"
|
||||||
|
Или ВозвращаемоеЧисло <> 1 Тогда
|
||||||
|
ВызватьИсключение "Не удалось вызвать Method2";
|
||||||
|
КонецЕсли;
|
||||||
|
|
||||||
Конец = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
Конец = ТекущаяУниверсальнаяДатаВМиллисекундах();
|
||||||
Сообщить(СтрШаблон("Длительность: %1", Конец - Начало));
|
Сообщить(СтрШаблон("Длительность: %1", Конец - Начало));
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::ffi::{Addin, Connection, ParamValue, ReturnValue, Tm};
|
use crate::ffi::{Addin, Connection, ParamValue, Tm, Variant};
|
||||||
use utf16_lit::utf16_null;
|
use utf16_lit::{utf16, utf16_null};
|
||||||
|
|
||||||
const PROPS: &[&[u16]] = &[
|
const PROPS: &[&[u16]] = &[
|
||||||
&utf16_null!("Test"),
|
&utf16_null!("Test"),
|
||||||
@ -11,7 +11,7 @@ const PROPS: &[&[u16]] = &[
|
|||||||
&utf16_null!("PropBlob"),
|
&utf16_null!("PropBlob"),
|
||||||
];
|
];
|
||||||
|
|
||||||
const METHODS: &[&[u16]] = &[&utf16_null!("Method1")];
|
const METHODS: &[&[u16]] = &[&utf16_null!("Method1"), &utf16_null!("Method2")];
|
||||||
|
|
||||||
pub struct Addin1 {
|
pub struct Addin1 {
|
||||||
test: i32,
|
test: i32,
|
||||||
@ -61,10 +61,10 @@ impl Addin for Addin1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_prop_name(&mut self, num: usize, _alias: usize) -> Option<&'static [u16]> {
|
fn get_prop_name(&mut self, num: usize, _alias: usize) -> Option<&'static [u16]> {
|
||||||
PROPS.get(num).map(|&x| x)
|
PROPS.get(num).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_prop_val(&mut self, num: usize, val: ReturnValue) -> bool {
|
fn get_prop_val(&mut self, num: usize, val: &mut Variant) -> bool {
|
||||||
match num {
|
match num {
|
||||||
0 => val.set_i32(self.test),
|
0 => val.set_i32(self.test),
|
||||||
1 => val.set_i32(self.prop_i32),
|
1 => val.set_i32(self.prop_i32),
|
||||||
@ -73,10 +73,10 @@ impl Addin for Addin1 {
|
|||||||
4 => val.set_date(self.prop_date),
|
4 => val.set_date(self.prop_date),
|
||||||
5 => {
|
5 => {
|
||||||
let s: Vec<u16> = self.prop_str.encode_utf16().collect();
|
let s: Vec<u16> = self.prop_str.encode_utf16().collect();
|
||||||
val.set_str(s.as_slice());
|
return val.set_str(s.as_slice());
|
||||||
}
|
}
|
||||||
6 => {
|
6 => {
|
||||||
val.set_blob(self.prop_blob.as_slice());
|
return val.set_blob(self.prop_blob.as_slice());
|
||||||
}
|
}
|
||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
@ -165,12 +165,13 @@ impl Addin for Addin1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_method_name(&mut self, num: usize, _alias: usize) -> Option<&'static [u16]> {
|
fn get_method_name(&mut self, num: usize, _alias: usize) -> Option<&'static [u16]> {
|
||||||
METHODS.get(num).map(|&x| x)
|
METHODS.get(num).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_n_params(&mut self, num: usize) -> usize {
|
fn get_n_params(&mut self, num: usize) -> usize {
|
||||||
match num {
|
match num {
|
||||||
0 => 3,
|
0 => 3,
|
||||||
|
1 => 2,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,7 +180,7 @@ impl Addin for Addin1 {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_method_num: usize,
|
_method_num: usize,
|
||||||
_param_num: usize,
|
_param_num: usize,
|
||||||
_value: ReturnValue,
|
_value: Variant,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -187,25 +188,48 @@ impl Addin for Addin1 {
|
|||||||
fn has_ret_val(&mut self, num: usize) -> bool {
|
fn has_ret_val(&mut self, num: usize) -> bool {
|
||||||
match num {
|
match num {
|
||||||
0 => true,
|
0 => true,
|
||||||
|
1 => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_as_proc(&mut self, _num: usize, _params: &[ParamValue]) -> bool {
|
fn call_as_proc(&mut self, _num: usize, _params: &mut [Variant]) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_as_func(&mut self, num: usize, params: &[ParamValue], ret_value: ReturnValue) -> bool {
|
fn call_as_func(
|
||||||
|
&mut self,
|
||||||
|
num: usize,
|
||||||
|
params: &mut [Variant],
|
||||||
|
ret_value: &mut Variant,
|
||||||
|
) -> bool {
|
||||||
match num {
|
match num {
|
||||||
0 => {
|
0 => {
|
||||||
let mut buf = Vec::<u16>::new();
|
let mut buf = Vec::<u16>::new();
|
||||||
for p in params {
|
for param in params {
|
||||||
match p {
|
match param.get() {
|
||||||
ParamValue::Str(x) => buf.extend_from_slice(x),
|
ParamValue::Str(x) => buf.extend_from_slice(x),
|
||||||
_ => return false,
|
_ => return false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret_value.set_str(buf.as_slice());
|
ret_value.set_str(buf.as_slice())
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
for (i, param) in params.iter_mut().enumerate() {
|
||||||
|
match param.get() {
|
||||||
|
ParamValue::Empty => {
|
||||||
|
if i == 0 {
|
||||||
|
if !param.set_str(&utf16!("Return value")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
param.set_i32(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret_value.set_bool(true);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::ffi::{Addin, Connection, ParamValue, ReturnValue};
|
use crate::ffi::{Addin, Connection, ParamValue, Variant};
|
||||||
use utf16_lit::utf16_null;
|
use utf16_lit::utf16_null;
|
||||||
|
|
||||||
pub struct Addin2 {
|
pub struct Addin2 {
|
||||||
@ -12,20 +12,15 @@ impl Addin2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Addin2 {
|
impl Drop for Addin2 {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Addin for Addin2 {
|
impl Addin for Addin2 {
|
||||||
fn init(&mut self, _interface: &'static Connection) -> bool {
|
fn init(&mut self, _interface: &'static Connection) -> bool {
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn done(&mut self) {
|
fn done(&mut self) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register_extension_as(&mut self) -> &'static [u16] {
|
fn register_extension_as(&mut self) -> &'static [u16] {
|
||||||
&utf16_null!("Class2")
|
&utf16_null!("Class2")
|
||||||
@ -51,7 +46,7 @@ impl Addin for Addin2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_prop_val(&mut self, num: usize, val: ReturnValue) -> bool {
|
fn get_prop_val(&mut self, num: usize, val: &mut Variant) -> bool {
|
||||||
match num {
|
match num {
|
||||||
0 => {
|
0 => {
|
||||||
val.set_i32(self.test1);
|
val.set_i32(self.test1);
|
||||||
@ -93,7 +88,7 @@ impl Addin for Addin2 {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_method_num: usize,
|
_method_num: usize,
|
||||||
_param_num: usize,
|
_param_num: usize,
|
||||||
_value: ReturnValue,
|
_value: Variant,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -102,15 +97,15 @@ impl Addin for Addin2 {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_as_proc(&mut self, _method_num: usize, _params: &[ParamValue]) -> bool {
|
fn call_as_proc(&mut self, _method_num: usize, _params: &mut [Variant]) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_as_func(
|
fn call_as_func(
|
||||||
&mut self,
|
&mut self,
|
||||||
_method_num: usize,
|
_method_num: usize,
|
||||||
_params: &[ParamValue],
|
_params: &mut [Variant],
|
||||||
_val: ReturnValue,
|
_val: &mut Variant,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
262
src/ffi.rs
262
src/ffi.rs
@ -1,15 +1,18 @@
|
|||||||
use std::{
|
use std::{
|
||||||
ffi::{c_int, c_long, c_ulong, c_void},
|
ffi::{c_int, c_long, c_ulong, c_void},
|
||||||
|
mem::MaybeUninit,
|
||||||
ptr::{self, NonNull},
|
ptr::{self, NonNull},
|
||||||
slice::{from_raw_parts, from_raw_parts_mut},
|
slice::{from_raw_parts, from_raw_parts_mut},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const MAX_PARAMS: usize = 8;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum AttachType {
|
pub enum AttachType {
|
||||||
CanAttachNotIsolated = 1,
|
NotIsolated = 1,
|
||||||
CanAttachIsolated,
|
Isolated,
|
||||||
CanAttachAny,
|
Any,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -31,87 +34,106 @@ pub struct Tm {
|
|||||||
pub zone: std::ffi::c_char, // timezone abbreviation
|
pub zone: std::ffi::c_char, // timezone abbreviation
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReturnValue<'a> {
|
pub struct Variant<'a> {
|
||||||
mem: &'a MemoryManager,
|
mem: &'a MemoryManager,
|
||||||
variant: &'a mut TVariant,
|
variant: &'a mut TVariant,
|
||||||
result: &'a mut bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl<'a> ReturnValue<'a> {
|
impl<'a> Variant<'a> {
|
||||||
pub fn set_empty(self) {
|
pub fn get(&self) -> ParamValue {
|
||||||
self.variant.vt = VariantType::EMPTY;
|
ParamValue::from(self.variant as &_)
|
||||||
}
|
}
|
||||||
pub fn set_i32(self, val: i32) {
|
fn free_memory(&mut self) {
|
||||||
|
match self.variant.vt {
|
||||||
|
VariantType::Pwstr => unsafe {
|
||||||
|
self.mem.free_str(&mut self.variant.value.data_str.ptr)
|
||||||
|
},
|
||||||
|
VariantType::Blob => unsafe {
|
||||||
|
self.mem.free_blob(&mut self.variant.value.data_blob.ptr)
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn set_empty(&mut self) {
|
||||||
|
self.free_memory();
|
||||||
|
self.variant.vt = VariantType::Empty;
|
||||||
|
}
|
||||||
|
pub fn set_i32(&mut self, val: i32) {
|
||||||
|
self.free_memory();
|
||||||
self.variant.vt = VariantType::I4;
|
self.variant.vt = VariantType::I4;
|
||||||
self.variant.value.i32 = val;
|
self.variant.value.i32 = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_bool(self, val: bool) {
|
pub fn set_bool(&mut self, val: bool) {
|
||||||
self.variant.vt = VariantType::BOOL;
|
self.free_memory();
|
||||||
|
self.variant.vt = VariantType::Bool;
|
||||||
self.variant.value.bool = val;
|
self.variant.value.bool = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_f64(self, val: f64) {
|
pub fn set_f64(&mut self, val: f64) {
|
||||||
|
self.free_memory();
|
||||||
self.variant.vt = VariantType::R8;
|
self.variant.vt = VariantType::R8;
|
||||||
self.variant.value.f64 = val;
|
self.variant.value.f64 = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_date(self, val: Tm) {
|
pub fn set_date(&mut self, val: Tm) {
|
||||||
|
self.free_memory();
|
||||||
self.variant.vt = VariantType::TM;
|
self.variant.vt = VariantType::TM;
|
||||||
self.variant.value.tm = val;
|
self.variant.value.tm = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_str(self, val: &[u16]) {
|
#[must_use]
|
||||||
|
pub fn set_str(&mut self, val: &[u16]) -> bool {
|
||||||
let Some(ptr) = self.mem.alloc_str(val.len()) else {
|
let Some(ptr) = self.mem.alloc_str(val.len()) else {
|
||||||
*self.result = false;
|
return false;
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
|
self.free_memory();
|
||||||
|
|
||||||
unsafe { ptr::copy_nonoverlapping(val.as_ptr(), ptr.as_ptr(), val.len()) };
|
unsafe { ptr::copy_nonoverlapping(val.as_ptr(), ptr.as_ptr(), val.len()) };
|
||||||
|
|
||||||
self.variant.vt = VariantType::PWSTR;
|
self.variant.vt = VariantType::Pwstr;
|
||||||
self.variant.value.data_str.ptr = ptr.as_ptr();
|
self.variant.value.data_str.ptr = ptr.as_ptr();
|
||||||
self.variant.value.data_str.len = val.len() as u32;
|
self.variant.value.data_str.len = val.len() as u32;
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_blob(self, val: &[u8]) {
|
#[must_use]
|
||||||
|
pub fn set_blob(&mut self, val: &[u8]) -> bool {
|
||||||
let Some(ptr) = self.mem.alloc_blob(val.len()) else {
|
let Some(ptr) = self.mem.alloc_blob(val.len()) else {
|
||||||
*self.result = false;
|
return false;
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
|
self.free_memory();
|
||||||
|
|
||||||
unsafe { ptr::copy_nonoverlapping(val.as_ptr(), ptr.as_ptr(), val.len()) };
|
unsafe { ptr::copy_nonoverlapping(val.as_ptr(), ptr.as_ptr(), val.len()) };
|
||||||
|
|
||||||
self.variant.vt = VariantType::BLOB;
|
self.variant.vt = VariantType::Blob;
|
||||||
self.variant.value.data_blob.ptr = ptr.as_ptr();
|
self.variant.value.data_blob.ptr = ptr.as_ptr();
|
||||||
self.variant.value.data_blob.len = val.len() as u32;
|
self.variant.value.data_blob.len = val.len() as u32;
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc_str(self, len: usize) -> Option<&'a mut [u16]> {
|
pub fn alloc_str(&mut self, len: usize) -> Option<&'a mut [u16]> {
|
||||||
let Some(ptr) = self.mem.alloc_str(len) else {
|
let Some(ptr) = self.mem.alloc_str(len) else {
|
||||||
*self.result = false;
|
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe { ptr::write_bytes(ptr.as_ptr(), 0, len) };
|
self.free_memory();
|
||||||
|
|
||||||
self.variant.vt = VariantType::PWSTR;
|
self.variant.vt = VariantType::Pwstr;
|
||||||
self.variant.value.data_str.ptr = ptr.as_ptr();
|
self.variant.value.data_str.ptr = ptr.as_ptr();
|
||||||
self.variant.value.data_str.len = len as u32;
|
self.variant.value.data_str.len = len as u32;
|
||||||
|
|
||||||
Some(unsafe { from_raw_parts_mut(ptr.as_ptr(), len) })
|
Some(unsafe { from_raw_parts_mut(ptr.as_ptr(), len) })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc_blob(self, len: usize) -> Option<&'a mut [u8]> {
|
pub fn alloc_blob(&mut self, len: usize) -> Option<&'a mut [u8]> {
|
||||||
let Some(ptr) = self.mem.alloc_blob(len) else {
|
let Some(ptr) = self.mem.alloc_blob(len) else {
|
||||||
*self.result = false;
|
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
self.free_memory();
|
||||||
|
|
||||||
unsafe { ptr::write_bytes(ptr.as_ptr(), 0, len) };
|
self.variant.vt = VariantType::Blob;
|
||||||
|
|
||||||
self.variant.vt = VariantType::BLOB;
|
|
||||||
self.variant.value.data_blob.ptr = ptr.as_ptr();
|
self.variant.value.data_blob.ptr = ptr.as_ptr();
|
||||||
self.variant.value.data_blob.len = len as u32;
|
self.variant.value.data_blob.len = len as u32;
|
||||||
|
|
||||||
@ -133,16 +155,16 @@ impl<'a> From<&'a TVariant> for ParamValue<'a> {
|
|||||||
fn from(param: &'a TVariant) -> ParamValue {
|
fn from(param: &'a TVariant) -> ParamValue {
|
||||||
unsafe {
|
unsafe {
|
||||||
match param.vt {
|
match param.vt {
|
||||||
VariantType::EMPTY => Self::Empty,
|
VariantType::Empty => Self::Empty,
|
||||||
VariantType::BOOL => Self::Bool(param.value.bool),
|
VariantType::Bool => Self::Bool(param.value.bool),
|
||||||
VariantType::I4 => Self::I32(param.value.i32),
|
VariantType::I4 => Self::I32(param.value.i32),
|
||||||
VariantType::R8 => Self::F64(param.value.f64),
|
VariantType::R8 => Self::F64(param.value.f64),
|
||||||
VariantType::TM => Self::Date(param.value.tm),
|
VariantType::TM => Self::Date(param.value.tm),
|
||||||
VariantType::PWSTR => Self::Str(from_raw_parts(
|
VariantType::Pwstr => Self::Str(from_raw_parts(
|
||||||
param.value.data_str.ptr,
|
param.value.data_str.ptr,
|
||||||
param.value.data_str.len as usize,
|
param.value.data_str.len as usize,
|
||||||
)),
|
)),
|
||||||
VariantType::BLOB => Self::Blob(from_raw_parts(
|
VariantType::Blob => Self::Blob(from_raw_parts(
|
||||||
param.value.data_blob.ptr,
|
param.value.data_blob.ptr,
|
||||||
param.value.data_blob.len as usize,
|
param.value.data_blob.len as usize,
|
||||||
)),
|
)),
|
||||||
@ -155,33 +177,33 @@ impl<'a> From<&'a TVariant> for ParamValue<'a> {
|
|||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
enum VariantType {
|
enum VariantType {
|
||||||
EMPTY = 0,
|
Empty = 0,
|
||||||
NULL,
|
Null,
|
||||||
I2, //int16_t
|
I2, //int16_t
|
||||||
I4, //int32_t
|
I4, //int32_t
|
||||||
R4, //float
|
R4, //float
|
||||||
R8, //double
|
R8, //double
|
||||||
DATE, //DATE (double)
|
Date, //DATE (double)
|
||||||
TM, //struct tm
|
TM, //struct tm
|
||||||
PSTR, //struct str string
|
Pstr, //struct str string
|
||||||
INTERFACE, //struct iface
|
Interface, //struct iface
|
||||||
ERROR, //int32_t errCode
|
Error, //int32_t errCode
|
||||||
BOOL, //bool
|
Bool, //bool
|
||||||
VARIANT, //struct _tVariant *
|
Variant, //struct _tVariant *
|
||||||
I1, //int8_t
|
I1, //int8_t
|
||||||
UI1, //uint8_t
|
Ui1, //uint8_t
|
||||||
UI2, //uint16_t
|
Ui2, //uint16_t
|
||||||
UI4, //uint32_t
|
Ui4, //uint32_t
|
||||||
I8, //int64_t
|
I8, //int64_t
|
||||||
UI8, //uint64_t
|
Ui8, //uint64_t
|
||||||
INT, //int Depends on architecture
|
Int, //int Depends on architecture
|
||||||
UINT, //unsigned int Depends on architecture
|
Uint, //unsigned int Depends on architecture
|
||||||
HRESULT, //long hRes
|
Hresult, //long hRes
|
||||||
PWSTR, //struct wstr
|
Pwstr, //struct wstr
|
||||||
BLOB, //means in struct str binary data contain
|
Blob, //means in struct str binary data contain
|
||||||
CLSID, //UUID
|
Clsid, //UUID
|
||||||
|
|
||||||
UNDEFINED = 0xFFFF,
|
Undefined = 0xFFFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -227,7 +249,7 @@ pub trait Addin {
|
|||||||
fn get_n_props(&mut self) -> usize;
|
fn get_n_props(&mut self) -> usize;
|
||||||
fn find_prop(&mut self, name: &[u16]) -> Option<usize>;
|
fn find_prop(&mut self, name: &[u16]) -> Option<usize>;
|
||||||
fn get_prop_name(&mut self, num: usize, alias: usize) -> Option<&'static [u16]>;
|
fn get_prop_name(&mut self, num: usize, alias: usize) -> Option<&'static [u16]>;
|
||||||
fn get_prop_val(&mut self, num: usize, val: ReturnValue) -> bool;
|
fn get_prop_val(&mut self, num: usize, val: &mut Variant) -> bool;
|
||||||
fn set_prop_val(&mut self, num: usize, val: &ParamValue) -> bool;
|
fn set_prop_val(&mut self, num: usize, val: &ParamValue) -> bool;
|
||||||
fn is_prop_readable(&mut self, num: usize) -> bool;
|
fn is_prop_readable(&mut self, num: usize) -> bool;
|
||||||
fn is_prop_writable(&mut self, num: usize) -> bool;
|
fn is_prop_writable(&mut self, num: usize) -> bool;
|
||||||
@ -235,15 +257,15 @@ pub trait Addin {
|
|||||||
fn find_method(&mut self, name: &[u16]) -> Option<usize>;
|
fn find_method(&mut self, name: &[u16]) -> Option<usize>;
|
||||||
fn get_method_name(&mut self, num: usize, alias: usize) -> Option<&'static [u16]>;
|
fn get_method_name(&mut self, num: usize, alias: usize) -> Option<&'static [u16]>;
|
||||||
fn get_n_params(&mut self, num: usize) -> usize;
|
fn get_n_params(&mut self, num: usize) -> usize;
|
||||||
fn get_param_def_value(
|
fn get_param_def_value(&mut self, method_num: usize, param_num: usize, value: Variant) -> bool;
|
||||||
|
fn has_ret_val(&mut self, method_num: usize) -> bool;
|
||||||
|
fn call_as_proc(&mut self, method_num: usize, params: &mut [Variant]) -> bool;
|
||||||
|
fn call_as_func(
|
||||||
&mut self,
|
&mut self,
|
||||||
method_num: usize,
|
method_num: usize,
|
||||||
param_num: usize,
|
params: &mut [Variant],
|
||||||
value: ReturnValue,
|
val: &mut Variant,
|
||||||
) -> bool;
|
) -> bool;
|
||||||
fn has_ret_val(&mut self, method_num: usize) -> bool;
|
|
||||||
fn call_as_proc(&mut self, method_num: usize, params: &[ParamValue]) -> bool;
|
|
||||||
fn call_as_func(&mut self, method_num: usize, params: &[ParamValue], val: ReturnValue) -> bool;
|
|
||||||
fn set_locale(&mut self, loc: &[u16]);
|
fn set_locale(&mut self, loc: &[u16]);
|
||||||
fn set_user_interface_language_code(&mut self, lang: &[u16]);
|
fn set_user_interface_language_code(&mut self, lang: &[u16]);
|
||||||
}
|
}
|
||||||
@ -319,13 +341,12 @@ struct LanguageExtenderBaseVTable<T: Addin> {
|
|||||||
get_param_def_value:
|
get_param_def_value:
|
||||||
unsafe extern "system" fn(&mut This<1, T>, c_long, c_long, &mut TVariant) -> bool,
|
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,
|
has_ret_val: unsafe extern "system" fn(&mut This<1, T>, c_long) -> bool,
|
||||||
call_as_proc:
|
call_as_proc: unsafe extern "system" fn(&mut This<1, T>, c_long, *mut TVariant, c_long) -> bool,
|
||||||
unsafe extern "system" fn(&mut This<1, T>, c_long, *const TVariant, c_long) -> bool,
|
|
||||||
call_as_func: unsafe extern "system" fn(
|
call_as_func: unsafe extern "system" fn(
|
||||||
&mut This<1, T>,
|
&mut This<1, T>,
|
||||||
c_long,
|
c_long,
|
||||||
&mut TVariant,
|
&mut TVariant,
|
||||||
*const TVariant,
|
*mut TVariant,
|
||||||
c_long,
|
c_long,
|
||||||
) -> bool,
|
) -> bool,
|
||||||
}
|
}
|
||||||
@ -394,13 +415,10 @@ unsafe extern "system" fn get_prop_val<T: Addin>(
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = true;
|
let mut return_value = Variant { mem, variant: val };
|
||||||
let return_value = ReturnValue {
|
component
|
||||||
mem,
|
.addin
|
||||||
variant: val,
|
.get_prop_val(num as usize, &mut return_value)
|
||||||
result: &mut result,
|
|
||||||
};
|
|
||||||
component.addin.get_prop_val(num as usize, return_value) && result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "system" fn set_prop_val<T: Addin>(
|
unsafe extern "system" fn set_prop_val<T: Addin>(
|
||||||
@ -446,7 +464,10 @@ unsafe extern "system" fn get_method_name<T: Addin>(
|
|||||||
let Some(allocator) = component.memory else {
|
let Some(allocator) = component.memory else {
|
||||||
return ptr::null();
|
return ptr::null();
|
||||||
};
|
};
|
||||||
let Some(method_name) = component.addin.get_method_name(num as usize, alias as usize) else {
|
let Some(method_name) = component
|
||||||
|
.addin
|
||||||
|
.get_method_name(num as usize, alias as usize)
|
||||||
|
else {
|
||||||
return ptr::null();
|
return ptr::null();
|
||||||
};
|
};
|
||||||
let Some(ptr) = allocator.alloc_str(method_name.len()) else {
|
let Some(ptr) = allocator.alloc_str(method_name.len()) else {
|
||||||
@ -460,7 +481,9 @@ unsafe extern "system" fn get_method_name<T: Addin>(
|
|||||||
|
|
||||||
unsafe extern "system" fn get_n_params<T: Addin>(this: &mut This<1, T>, num: c_long) -> c_long {
|
unsafe extern "system" fn get_n_params<T: Addin>(this: &mut This<1, T>, num: c_long) -> c_long {
|
||||||
let component = this.get_component();
|
let component = this.get_component();
|
||||||
component.addin.get_n_params(num as usize) as c_long
|
let count = component.addin.get_n_params(num as usize);
|
||||||
|
assert!(count <= MAX_PARAMS, "too many parameters");
|
||||||
|
count as _
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "system" fn get_param_def_value<T: Addin>(
|
unsafe extern "system" fn get_param_def_value<T: Addin>(
|
||||||
@ -474,17 +497,11 @@ unsafe extern "system" fn get_param_def_value<T: Addin>(
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = true;
|
let return_value = Variant { mem, variant: val };
|
||||||
let return_value = ReturnValue {
|
|
||||||
mem,
|
|
||||||
variant: val,
|
|
||||||
result: &mut result,
|
|
||||||
};
|
|
||||||
|
|
||||||
component
|
component
|
||||||
.addin
|
.addin
|
||||||
.get_param_def_value(method_num as usize, param_num as usize, return_value)
|
.get_param_def_value(method_num as usize, param_num as usize, return_value)
|
||||||
&& result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "system" fn has_ret_val<T: Addin>(this: &mut This<1, T>, method_num: c_long) -> bool {
|
unsafe extern "system" fn has_ret_val<T: Addin>(this: &mut This<1, T>, method_num: c_long) -> bool {
|
||||||
@ -495,25 +512,7 @@ unsafe extern "system" fn has_ret_val<T: Addin>(this: &mut This<1, T>, method_nu
|
|||||||
unsafe extern "system" fn call_as_proc<T: Addin>(
|
unsafe extern "system" fn call_as_proc<T: Addin>(
|
||||||
this: &mut This<1, T>,
|
this: &mut This<1, T>,
|
||||||
method_num: c_long,
|
method_num: c_long,
|
||||||
params: *const TVariant,
|
params: *mut 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))
|
|
||||||
.collect::<Vec<ParamValue>>();
|
|
||||||
|
|
||||||
component
|
|
||||||
.addin
|
|
||||||
.call_as_proc(method_num as usize, param_values.as_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe extern "system" fn call_as_func<T: Addin>(
|
|
||||||
this: &mut This<1, T>,
|
|
||||||
method_num: c_long,
|
|
||||||
ret_value: &mut TVariant,
|
|
||||||
params: *const TVariant,
|
|
||||||
size_array: c_long,
|
size_array: c_long,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let component = this.get_component();
|
let component = this.get_component();
|
||||||
@ -521,22 +520,53 @@ unsafe extern "system" fn call_as_func<T: Addin>(
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = true;
|
let size_array = size_array as usize;
|
||||||
let return_value = ReturnValue {
|
|
||||||
mem,
|
|
||||||
variant: ret_value,
|
|
||||||
result: &mut result,
|
|
||||||
};
|
|
||||||
|
|
||||||
let param_values = from_raw_parts(params, size_array as usize)
|
let mut param_values: [MaybeUninit<Variant>; MAX_PARAMS] = MaybeUninit::uninit().assume_init();
|
||||||
.iter()
|
for (x1, x2) in from_raw_parts_mut(params, size_array)
|
||||||
.map(|x| ParamValue::from(x))
|
.iter_mut()
|
||||||
.collect::<Vec<ParamValue>>();
|
.zip(param_values.iter_mut())
|
||||||
|
{
|
||||||
|
x2.write(Variant { mem, variant: x1 });
|
||||||
|
}
|
||||||
|
let param_values = std::mem::transmute(&mut param_values[..size_array]);
|
||||||
|
|
||||||
component
|
component
|
||||||
.addin
|
.addin
|
||||||
.call_as_func(method_num as usize, param_values.as_slice(), return_value)
|
.call_as_proc(method_num as usize, param_values)
|
||||||
&& result
|
}
|
||||||
|
|
||||||
|
unsafe extern "system" fn call_as_func<T: Addin>(
|
||||||
|
this: &mut This<1, T>,
|
||||||
|
method_num: c_long,
|
||||||
|
ret_value: &mut TVariant,
|
||||||
|
params: *mut TVariant,
|
||||||
|
size_array: c_long,
|
||||||
|
) -> bool {
|
||||||
|
let component = this.get_component();
|
||||||
|
let Some(mem) = component.memory else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let size_array = size_array as usize;
|
||||||
|
|
||||||
|
let mut return_value = Variant {
|
||||||
|
mem,
|
||||||
|
variant: ret_value,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut param_values: [MaybeUninit<Variant>; MAX_PARAMS] = MaybeUninit::uninit().assume_init();
|
||||||
|
for (x1, x2) in from_raw_parts_mut(params, size_array)
|
||||||
|
.iter_mut()
|
||||||
|
.zip(param_values.iter_mut())
|
||||||
|
{
|
||||||
|
x2.write(Variant { mem, variant: x1 });
|
||||||
|
}
|
||||||
|
let param_values = std::mem::transmute(&mut param_values[..size_array]);
|
||||||
|
|
||||||
|
component
|
||||||
|
.addin
|
||||||
|
.call_as_func(method_num as usize, param_values, &mut return_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -701,6 +731,18 @@ impl MemoryManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn free_str(&self, ptr: *mut *mut u16) {
|
||||||
|
unsafe {
|
||||||
|
(self.vptr.free_memory)(self, ptr as _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn free_blob(&self, ptr: *mut *mut u8) {
|
||||||
|
unsafe {
|
||||||
|
(self.vptr.free_memory)(self, ptr as _);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -54,5 +54,5 @@ pub unsafe extern "C" fn SetPlatformCapabilities(capabilities: c_int) -> c_int {
|
|||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn GetAttachType() -> AttachType {
|
pub extern "C" fn GetAttachType() -> AttachType {
|
||||||
AttachType::CanAttachAny
|
AttachType::Any
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user