Excel VBA调用Rust编写的DLL时参数传递异常问题求助
问题描述
尝试用Rust编写动态链接库(DLL)并在Excel中调用,已成功触发函数执行,但参数传递存在异常:
- 在Excel工作表中调用
add()时,弹窗显示参数始终为1,返回值固定为「代码中设定的偏移值+1」 - 执行VBA过程时触发运行时错误'28':栈空间不足
- 已尝试调整调用约定(
stdcall、cdecl)和整数类型(u32、i32),问题未解决 - 运行环境:64位机器,使用
cargo build --target x86_64-pc-windows-msvc编译适配架构的库
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代码
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
Cargo.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="*"
问题根源与修复方案
核心问题:调用约定与参数处理不匹配
- 64位平台调用约定特性:Win64平台仅有一种调用约定(Microsoft x64 calling convention),Rust中的
extern "stdcall"在x64架构下会被忽略,实际行为等同于extern "C",但VBA声明时的参数传递细节和栈平衡逻辑出现了偏差。 - 参数传递的细节错误:Rust代码中字符串格式化的写法冗余,且指针转换存在不必要的复杂操作,同时VBA的DLL路径可能未正确指向编译后的文件。
修复步骤
1. 调整Rust函数的导出与实现
直接使用extern "C"(Win64下与stdcall行为一致,写法更准确),简化指针操作:
#[cfg(target_arch="x86_64")] #[no_mangle] pub extern "C" fn pass_number(input: u32) -> u32 { let got = input.to_string(); // 简化字符串格式化逻辑 let c_string = CString::new(format!("{}", got)).unwrap(); unsafe { MessageBoxA( None, PCSTR(c_string.as_ptr()), // 直接使用CString的原生指针,避免冗余转换 s!("pass_number()"), MB_OK ); } input + 100 }
2. 修正VBA函数声明
确保DLL路径为绝对路径,同时确认参数类型匹配(64位Excel中Long为32位整数,与Rust的u32兼容):
Public Declare PtrSafe Function add Lib "C:\绝对路径\rustlib.dll" _ Alias "pass_number" (ByVal num As Long) As Long Sub test() MsgBox add(11) End Sub
3. 优化编译配置
使用release模式编译,提升稳定性:
cargo build --release --target x86_64-pc-windows-msvc
4. 解决栈空间不足问题
该错误本质是调用约定不匹配导致的栈平衡异常,修复上述调用约定和参数传递逻辑后,栈空间不足的问题会自动消失。
验证
替换旧DLL文件后,运行VBA的test过程:
- 弹窗应显示传入的参数(如11)
- 返回值应为11+100=111
- 无栈空间不足错误触发
内容的提问来源于stack exchange,提问作者JUSEOK KO
相关产品推荐
相关产品推荐

