【发布时间】:2017-04-18 18:17:44
【问题描述】:
我有 64 位 Windows 10 和 MS Office 64 位。我正在尝试让 PowerPoint 的 VBA 加载并执行自写的 64 位 Windows DLL 中的函数。
问题是我无法将字符串从 VBA 传递到 Windows DLL。在各种网站上有很多讨论,但我没有找到一个有效的。 我尝试了两种方法都没有成功。如果我使用调用 DLL 的 C++ 应用程序,我没有问题。
方法一:
DLL:
extern "C" {
__declspec(dllexport) long jaadd(long a, long b, LPCWSTR strg)
{
MessageBoxW(NULL, strg, L"DLL", MB_OK);
return a+b;
}
}
在 VBA 中:
Private Declare PtrSafe Function jaadd Lib "D:\\Visual Studio 2017\\Projects\\PopUpDLL\\x64\\Debug\\PopUpDLL.dll" _
(ByVal arg1 As Long, ByVal arg2 As Long, ByVal lParam As String) As Long
y = jaadd(1, 2, "abcdxxxxx")
结果: y = 3 这是正确的,但消息框显示象形文字。
方法 2 - 不使用宽字符串:
DLL:
extern "C" {
__declspec(dllexport) long jaadd(long a, long b, LPCSTR strg)
{
MessageBoxA(NULL, strg, "DLL", MB_OK);
return a+b;
}
}
VBA 是一样的
结果: y = 3 这是正确的,但消息框显示“无”。
收到任何帮助。
【问题讨论】:
-
VBA 中的字符串是
BSTR。可能是空终止符搞砸了。 -
@Mat'sMug: BSTR's 以零结尾,就像任何其他 C 风格的字符串一样。指针还指向第一个字符(不是长度前缀)。即使
LPCWSTR是错误的类型,它仍然可以安全地用作参数,如果它通过BSTR。 @JonAnthony:你能发布通过strg传递的缓冲区的内容吗(开始比指针低4 个字节)? -
不确定这在 VBA 中是否合法,但您可能必须具体说明编组,即
<MarshalAs(UnmanagedType.LPWStr)> lParam As String。 -
@Mat'sMug:
MarshalAs属性是 P/Invoke 声明的一部分,与 C# 中的相同。 VBA 也不需要知道LPCWSTR是什么。如果它通过了BSTR,C++ 代码应该没问题,即使它没有严格使用正确的类型。 -
@Mat'sMug:微软的 C++ 编译器也使用 32 位宽的
longs(参见 data type ranges),所以没有直接的额外问题(添加 n 位数字并将结果存储在无论如何,一个 n 位数字在 50% 的所有可能情况下都会溢出)。至于字符串类型:如果 VBA 实际上传递了BSTR,则库不需要转换任何内容。BSTR已经是一个有效的LPCWSTR。所以要么 VBA 没有通过BSTRs,要么封送器做了我不知道的事情。
标签: string windows vba dll parameters