2016-02-27 38 views
1

我創建從https://msdn.microsoft.com/de-de/library/ms235636.aspxMathFuncsDll.dll沒有問題。 我可以在不同的C++項目中使用數學函數也沒有問題。在Excel中使用C++ DLL VBA

現在我想在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; 
    } 
} 

回答

4

我想你知道,從一個VB程序調用C++庫時,你在做什麼,我指的是calling convention


問題是C++的名字是mangled

如果你看一看導出的函數的名稱(例如與dumpbin /EXPORTS MathFuncsDll.dll,他們的類似:

ordinal hint RVA  name 

     1 0 00001000 [email protected]@[email protected]@[email protected] 
     2 1 00001030 [email protected]@[email protected]@[email protected] 
     3 2 00001020 [email protected]@[email protected]@[email protected] 
     4 3 00001010 [email protected]@[email protected]@[email protected] 

我的輸出將與你不同,但它足以說明,有沒有簡單的像Add名。

通常你避免這種混亂與使用改性劑extern "C"
隨着微軟的編譯器,類承包商,客人的名字似乎總是錯位,所以它是沒有用在這裏。

您可以通過四種方式解決此:

1.定義DEF文件重命名功能

LIBRARY MathFuncsDll 
EXPORTS 
    [email protected]@[email protected]@[email protected] 
    ... 

2.使用正確的別名在VBA聲明

Public Declare Function DLL_Import_Add Lib "C:\Users\User\Desktop\MathFuncsDll.dll" Alias "[email protected]@[email protected]@[email protected]" (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++程序。

+0

這就是它!我試過'Add @ MyMathFuncs @ MathFuncs @@ SANNN @ Z',但我在開頭忘了'?'。我也在C中做了這個,並且用DEF文件在DLL中定義了函數的名稱,並且在那裏寫了'name_in_dll = name_in_c'。應該在你的答案中翻轉? – TimFinnegan

+1

@TimFinnegan哎呀,謝謝 –