C ++ GetProcAddress()找不到静态类的方法

时间:2014-10-14 16:28:26

标签: c++ dll dllexport dynamic-loading getprocaddress

我需要在C ++中动态加载dll。

我已按照本教程http://msdn.microsoft.com/en-us/library/ms235636.aspx创建了dll,一切正常。

然后我跟着这个http://msdn.microsoft.com/en-us/library/64tkc9y5.aspx,我调整了控制台应用程序如下:

typedef DOUBLE(CALLBACK* DllFunc)(DOUBLE, DOUBLE);

int _tmain(int argc, _TCHAR* argv[])
{
    HINSTANCE hDLL;               // Handle to DLL
    DllFunc dllFunc1;
    DOUBLE p1 = 1.0, p2 = 2.0, r;
    hDLL = LoadLibrary(L"MathFuncsDLL");
    if (hDLL != NULL)
    {
        cout <<  "DLL loaded: " << hDLL << endl;
        dllFunc1 = (DllFunc)GetProcAddress(hDLL, "MyMathFuncs@MathFuncs@Multiply");
        if (!dllFunc1)
        {
            // handle the error
            FreeLibrary(hDLL);
            cout << "Function not found!" << endl;
            return -1;
        }
        else
        {
            // call the function
            r = dllFunc1(p1, p2);
            cout << "The result is: " << r << endl;
        }               
    }
    else {
        cout << "Dll not found" << endl;
        return -1;
    }
    cout << "Press any key to exit." << endl;
    int i;
    cin >> i;
    return 0;
}

正确加载DLL并且它不为null。问题是GetProcAddress()函数总是返回0。

我尝试过使用Namespace,ClassName,Method name的每个组合。我试图在函数名中使用范围运算符(::)而不是@。

我试图将整个命名空间定义为      外部“C” 但没有变化。每次运行或调试控制台应用程序时,都无法找到“乘法”功能。

我想我错过了一些东西...... 我哪里错了?


修改

Dependency Walker向我展示了以下导出表:

DLL Export table

现在我想知道函数名的最后一部分意味着什么...... 为什么__declspec(dllexports)会添加这些符号?

2 个答案:

答案 0 :(得分:3)

欢迎使用C ++名称修改。编译器添加到函数名称的所有内容都是为了确保具有唯一签名的每个函数都具有唯一的名称。微软确实以一种方式命名,而GCC / Clang则另一种方式。它不是标准化的,但是特定操作系统上的编译器都以相同的方式命名,因此它们都可以相处。

确保您的名字可由人类预测的唯一方法是将导出的DLL函数声明为extern "C"。但是,这限制了您导出C函数。

在我曾经使用的库中,有一个导出的C函数来初始化库并返回一个接口指针。在这种情况下,“接口”表示一个抽象的虚拟基类,没有数据,只有虚函数。

这是声明接口类的正确方法:

struct my_interface
{
    virtual int my_function1( int param1, int param2 ) = 0;
    virtual int my_function2( const char *param ) = 0;

#if CHOOSE_DESTRUCTION_TYPE

protected:
    // Protected non-virtual destructor prevents the use of delete on the interface pointer.
    // Must be defined because it will be used as objects of derived types are destructed.
    ~my_interface() {};

#else

    // Public virtual destructor allows the use of delete on the interface pointer.
    virtual ~my_interface() = 0;

#endif

private:
    // Private copy assignment prevents "*ptr1 = *ptr2".
    // This odd syntax CAN be supported, but you probably shouldn't.
    // Only needs to be declared because nobody can call it.
    my_interface & operator=( const my_interface & );

    // Ditto for move assignment.
    my_interface & operator=( my_interface && );
};

答案 1 :(得分:2)

使用dumpbin或Dependency Viewer之类的工具检查导出的函数名称。这将允许您诊断哪种可能的故障模式适用于您的情况:

  1. 不导出该功能,或
  2. 导出该功能,但名称已装饰,或
  3. 使用您期望的名称导出该函数,但您输入的内容不正确。