我假设你知道自己在做什么当从 VB 程序调用 C++ 库时,我指的是调用约定 https://msdn.microsoft.com/en-us/library/984x0h58.aspx.
问题是 C++ 名称是mangled https://en.wikipedia.org/wiki/Name_mangling.
如果您查看导出的函数名称(例如dumpbin /EXPORTS MathFuncsDll.dll
,它们是这样的:
ordinal hint RVA name
1 0 00001000 ?Add@MyMathFuncs@MathFuncs@@SAHHH@Z
2 1 00001030 ?Divide@MyMathFuncs@MathFuncs@@SAHHH@Z
3 2 00001020 ?Multiply@MyMathFuncs@MathFuncs@@SAHHH@Z
4 3 00001010 ?Subtract@MyMathFuncs@MathFuncs@@SAHHH@Z
我的输出将与你的不同,但足以表明不存在像这样的简单名称Add
.
通常,您可以使用修饰符来避免这种混乱extern "C"
.
使用 Microsoft 编译器,类成员名称似乎总是被破坏,因此在这里毫无用处。
您可以通过四种方式解决此问题:
1. 定义一个DEF https://msdn.microsoft.com/en-us/library/d91k01sh.aspx重命名函数的文件
LIBRARY MathFuncsDll
EXPORTS
Add=?Add@MyMathFuncs@MathFuncs@@SAHHH@Z
...
2. 在 VBA 声明中使用正确的别名
Public Declare Function DLL_Import_Add Lib "C:\Users\User\Desktop\MathFuncsDll.dll" Alias "?Add@MyMathFuncs@MathFuncs@@SAHHH@Z" (ByVal a As Double, ByVal b As Double) As Double
3. 按序数导入,使用类似Alias "#1"
Public Declare Function DLL_Import_Add Lib "C:\Users\User\Desktop\MathFuncsDll.dll" Alias "#1" (ByVal a As Double, ByVal b As Double) As Double
4. 定义调用其等效项的全局存根函数
extern "C" MATHFUNCSDLL_API double Add(double a, double b)
{
return MathFuncs::MyMathFuncs::Add(a, b);
}
并导出它们。
这一切都不是完美的,请记住,损坏的名称是特定于编译器的,如果您使用它们并更改/更新编译器,事情可能会崩溃。
序数也不是固定的,除非你使用DEF文件(再次需要损坏的名称)。
最后一个选项对于更改调用约定很有用,并且不会更改原始函数的导出方式,从而允许访问 C++ 和非 C++ 程序。