我从https://msdn.microsoft.com/de-de/library/ms235636.aspx创建MathFuncsDll.dll
没有问题。
我也可以在不同的C ++项目中使用数学函数而没有问题。
现在我想在Excel VBA中使用这些功能。我试过了:
Public Declare Function DLL_Import_Add Lib "C:\Users\User\Desktop\MathFuncsDll.dll" Alias "Add" (ByVal a As Double, ByVal b As Double) As Double
Sub test()
MsgBox DLL_Import_Add(2.1, 3.3)
End Sub
但我收到Run-time error '453'
无法找到DLL入口点。
我该如何解决这个问题?
MathFuncsDll.h:
// MathFuncsDll.h
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif
namespace MathFuncs
{
// This class is exported from the MathFuncsDll.dll
class MyMathFuncs
{
public:
// Returns a + b
static MATHFUNCSDLL_API double Add(double a, double b);
// Returns a - b
static MATHFUNCSDLL_API double Subtract(double a, double b);
// Returns a * b
static MATHFUNCSDLL_API double Multiply(double a, double b);
// Returns a / b
// Throws const std::invalid_argument& if b is 0
static MATHFUNCSDLL_API double Divide(double a, double b);
};
}
MathFuncsDll.cpp:
// MathFuncsDll.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "MathFuncsDll.h"
#include <stdexcept>
using namespace std;
namespace MathFuncs
{
double MyMathFuncs::Add(double a, double b)
{
return a + b;
}
double MyMathFuncs::Subtract(double a, double b)
{
return a - b;
}
double MyMathFuncs::Multiply(double a, double b)
{
return a * b;
}
double MyMathFuncs::Divide(double a, double b)
{
if (b == 0)
{
throw invalid_argument("b cannot be zero!");
}
return a / b;
}
}
答案 0 :(得分:5)
我假设您知道自己在做什么从VB程序调用C ++库时,我指的是calling convention。
问题是C ++名称是mangled。
如果您查看导出的函数名称(例如使用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编译器,类memebers名称似乎总是被破坏,所以在这里没用。
您可以通过以下四种方式解决此问题:
<强> 1。定义重命名功能的DEF
文件
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 ++程序。