在Excel VBA中使用C ++ DLL [英] Using C++ DLL in Excel VBA

查看:93
本文介绍了在Excel VBA中使用C ++ DLL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从 https创建了 MathFuncsDll.dll ://msdn.microsoft.com/de-de/library/ms235636.aspx 没有问题.我也可以在其他C ++项目中使用数学函数.

I created the MathFuncsDll.dll from https://msdn.microsoft.com/de-de/library/ms235636.aspx without issues. I can use the math functions in a different C++ project also without issues.

现在,我想在Excel VBA中使用这些功能.我试过了:

Now I want to use these functions in Excel VBA. I tried:

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

但是我收到一个运行时错误'453'找不到DLL入口点.

But I am receiving a Run-time error '453' The DLL entry point cannot be found.

我该如何解决这个问题?

How can I solve that problem?

MathFuncsDll.h:

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:

// 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;
    }
}

推荐答案

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

问题是C ++名称被被弄乱了.

The problem is that C++ names are mangled.

如果您查看导出的函数名称(例如,使用 dumpbin/EXPORTS MathFuncsDll.dll ,则它们类似于以下内容:

If you take a look at the exported functions names (for example with dumpbin /EXPORTS MathFuncsDll.dll, they are something like these:

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 这样的简单名称.

My output will differ from yours, but it suffices to show that there are no simple names like Add.

通常,使用修饰符 extern"C" 可以避免这种混乱情况.
使用Microsoft编译器,类成员名称似乎总是被修饰,因此在这里是没有用的.

Usually you avoid this mess with the use of the modifier extern "C".
With Microsoft compiler, class memebers names seem to be always mangled, so it is useless here.

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

You can workaround this in four ways:

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"

3. Import by ordinal, using something like 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); 
} 

并导出它们.

这都不是完美的,请记住,损坏的名称是特定于编译器的,如果使用它们并更改/更新编译器,则事情可能会崩溃.

None of this is perfect, keep in mind that mangled names are compiler specific, if you use them and change/update the compiler, things may break up.

除非您使用 DEF 文件(同样需要重新命名的文件),否则序号也不固定.

Also ordinals are not fixed, unless you use a DEF file (that again need the mangled name).

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

The last option is useful to change calling convention and won't change the way the original functions are exported, thus allowing access to both C++ and non C++ programs.

这篇关于在Excel VBA中使用C ++ DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆