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

Windows 11下VBA向C++ DLL传递字符串问题:接收为空

问题概述

在64位Excel(版本2307 Build 16.0.16626.20170)环境下,尝试将VBA字符串传递给Visual Studio 2022编译的x64 Debug版C++ DLL时,始终无法正常接收字符串(参数为空或乱码)。原32位环境下的代码可正常运行,升级64位后故障。已尝试LPSTR、BSTR、LPCSTR三种参数类型,均未解决问题。

尝试过的无效代码示例

1. LPSTR参数版本

C++代码:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <Windows.h>

extern "C" {
    __declspec(dllexport) void ShowMessage(LPSTR message) {
        MessageBoxA(NULL, message, "DLL Message", MB_OK);
    }
}

VBA代码:

'Declare function
Declare PtrSafe Function ShowMessage _
    Lib "MyFunTest.dll" (ByVal message As String)

Function VBShowName() As String
    Dim str_message As String
    str_message = "Hello World"
    ShowMessage (str_message)
    VBShowName = str_message
End Function

2. BSTR参数版本

C++代码:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <Windows.h>
#include <oleauto.h>

extern "C" {
    __declspec(dllexport) void ShowMessage(BSTR message) {
        MessageBoxW(NULL, message, L"DLL Message", MB_OK);
    }
}

3. LPCSTR参数版本

C++代码:

extern "C"  __declspec(dllexport) void __stdcall passByNarrowVal(LPCSTR s)
{
    USES_CONVERSION;
    MessageBox(NULL, A2W(s), L"Pass by Narrow Val", MB_OK | MB_ICONINFORMATION);
}

VBA代码:

Declare PtrSafe Function passByNarrowVal _
    Lib "MyFunTest.dll" (ByVal s As String)

Sub TestNarrow()
    Dim tline As String
    tline = "Hello World"
    passByNarrowVal (tline)
End Sub
解决方案

核心问题在于调用约定不匹配和字符串编码处理不当,64位环境下对这两点的要求比32位更严格。

1. 匹配调用约定

VBA的Declare语句默认使用__stdcall调用约定,C++函数必须显式声明该约定,否则会导致参数传递栈异常,出现空值或乱码。

2. 正确处理宽字符字符串(推荐方案)

64位VBA的String类型本质是UTF-16编码的BSTR,直接用BSTR作为C++函数参数是最可靠的方式:

正确C++ DLL代码

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <Windows.h>
#include <oleauto.h>

extern "C" {
    // 显式指定__stdcall调用约定,与VBA匹配
    __declspec(dllexport) void __stdcall ShowMessage(BSTR message) {
        // MessageBoxW接收宽字符,BSTR本身就是UTF-16格式,无需额外转换
        MessageBoxW(NULL, message, L"DLL Message", MB_OK);
    }
}

对应VBA代码

' 声明PtrSafe适配64位,默认StdCall调用约定与C++匹配
Declare PtrSafe Function ShowMessage _
    Lib "MyFunTest.dll" (ByVal message As String)

Function VBShowName() As String
    Dim str_message As String
    str_message = "Hello World"
    ' 调用时直接传递字符串,避免多余括号(括号会强制表达式求值,可能引发异常)
    ShowMessage str_message
    VBShowName = str_message
End Function

3. 可选:传递ANSI字符串(不推荐)

如果需要兼容旧的ANSI逻辑,需在VBA中手动转换编码:

C++代码

extern "C" {
    __declspec(dllexport) void __stdcall ShowAnsiMessage(LPCSTR message) {
        MessageBoxA(NULL, message, "DLL Message", MB_OK);
    }
}

VBA代码

Declare PtrSafe Function ShowAnsiMessage _
    Lib "MyFunTest.dll" (ByVal message As String)

Function VBShowAnsi() As String
    Dim str_message As String
    str_message = "Hello World"
    ' 将VBA的Unicode字符串转换为ANSI后传递
    ShowAnsiMessage StrConv(str_message, vbFromUnicode)
    VBShowAnsi = str_message
End Function

额外排查点

  • 确保DLL放置在Excel可访问路径(如Excel安装目录、系统目录,或与Excel文件同目录),避免加载旧版本DLL。
  • 调试时确认VS加载的是当前编译的x64 Debug版DLL,符号文件匹配。

内容的提问来源于stack exchange,提问作者Brian Howard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 07:30:28