我正在尝试编写动态库并从Excel使用它。
现在我可以从Excel调用我的函数,但似乎函数的参数传递方式错误。
我的Rust代码如下所示
use std::ffi::{c_char, CString};
use windows::core::{BSTR, PCSTR};
use windows::Win32::System::Com::{SAFEARRAY, VARIANT};
use windows::Win32::UI::WindowsAndMessaging::*;
use windows::s;
#[cfg(target_arch="x86_64")]
#[no_mangle]
pub extern "stdcall" fn pass_number(input: u32) -> u32 {
let got = input.to_string();
let c_string = CString::new("{}".replace("{}", &got)).unwrap();
let ptr_str = CString::as_bytes_with_nul(&c_string);
unsafe { MessageBoxA(None, PCSTR::from_raw(&(ptr_str[0]) as &u8 as *const u8), s!("pass_number()"), MB_OK); }
input + 100
}
和VBA代码来加载dll
Public Declare PtrSafe Function add Lib "PATH_TO_DLL" _
Alias "pass_number" (ByVal num As Long) As Long
Sub test()
MsgBox add(11)
End Sub
当我从Excel工作表调用add()
时,Windows消息框弹出,但got
的值总是1,无论我传递给它的参数。如果我执行VBA过程,它会引发运行时错误“28”,堆栈空间不足。
我尝试了不同的调用约定,如Win64、cdecl和参数的不同整数数据类型,但结果总是一样的。
从我可以看到Windows消息的事实,我猜我可以调用Excel的函数,但当参数传递给函数时出错了。
我在64位机器上运行该程序,库是使用cargo build --target x86_64-pc-windows-msvc
为这种架构编译的。
有人能告诉我丢失了什么吗?
- 更多信息
我测试了i32
作为pass_number()
的输入和输出数据类型,但没有任何变化。pass_number()
在Excel工作表中通过add()
调用时以某种方式返回,但返回值始终为'101'。然而,当我将Rust代码最后一行的数字100更改为new value
时,返回值更改为new value + 1
。
这是我的货物toml
[lib]
name="rustlib"
crate-type = ["cdylib"]
[dependencies.windows]
version = "0.48"
features = [
"Data_Xml_Dom",
"Win32_Foundation",
"Win32_System_Com",
"Win32_System_Ole",
"Win32_Security",
"Win32_System_Threading",
"Win32_UI_WindowsAndMessaging",
"Win32_System_WindowsProgramming",
]
[dependencies]
lazy_static = "*"
reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = {version = "*", features = ["rt-multi-thread"]}
futures="*"
1条答案
按热度按时间ebdffaop1#
通过安装32位Excel并创建32位DLL,我可以从Excel中调用DLL中的函数。但是仍然有一个问题,从Excel向dll传递指针类型(字符串,或数组)不能很好地工作。