You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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="*"
问题根源与修复方案

核心问题:调用约定与参数处理不匹配

  1. 64位平台调用约定特性:Win64平台仅有一种调用约定(Microsoft x64 calling convention),Rust中的extern "stdcall"在x64架构下会被忽略,实际行为等同于extern "C",但VBA声明时的参数传递细节和栈平衡逻辑出现了偏差。
  2. 参数传递的细节错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 20:23:13