在Excel VBA中使用C++ DLL

Tim*_*gan 2 c++ excel vba excel-vba

MathFuncsDll.dllhttps://msdn.microsoft.com/de-de/library/ms235636.aspx创建了没有问题的.我也可以在不同的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 Code Online (Sandbox Code Playgroud)

但是我收到了一个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);
    };
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*oom 6

我假设您从VB程序调用C++库时知道自己在做什么,我指的是调用约定.


问题是C++名称被破坏了.

如果您查看导出的函数名称(例如,使用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
Run Code Online (Sandbox Code Playgroud)

我的输出与你的输出不同,但它足以表明没有简单的名字Add.

通常你可以通过使用修饰符来避免这种混乱extern "C".
使用Microsoft编译器,类memebers名称似乎总是被破坏,所以在这里没用.

您可以通过以下四种方式解决此问题:

1.定义DEF重命名函数的文件

LIBRARY MathFuncsDll
EXPORTS
   Add=?Add@MyMathFuncs@MathFuncs@@SAHHH@Z
   ...
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

4.定义调用其等效项的全局存根函数

extern "C" MATHFUNCSDLL_API double Add(double a, double b)
{
   return MathFuncs::MyMathFuncs::Add(a, b); 
} 
Run Code Online (Sandbox Code Playgroud)

并导出它们.

这些都不是完美的,请记住,受损的名称是编译器特定的,如果您使用它们并更改/更新编译器,事情可能会破裂.

除非您使用DEF文件(再次需要损坏的名称),否则序数也不会修复.

最后一个选项对于更改调用约定非常有用,并且不会更改原始函数的导出方式,因此允许访问C++和非C++程序.