0

我正在尝试将 C++ DLL 链接到我将创建的新 C++ DLL,

我已经逐步按照下面的教程和许多其他教程进行操作,但是“GetProcAddress”函数返回NULL“ http://www.dreamincode.net/forums/topic/118076-dlls-explicit-linking/

这是我尝试从 DLL 调用的函数的原型:

int RemoveAllDataFile(unsigned int id);

该函数返回 1,因此 DLL 加载成功。

typedef int (*funcRemoveAllDataFile) (int);

int load_dll_ARbnet(int x)
{
    /* Retrieve DLL handle.*/
    HINSTANCE hDLL = LoadLibrary("ArbNet2Remote.dll");   
    if (hDLL == NULL)
    {
        return 0;
    }    
    else
    {
    }
    /*Get the function address*/
    funcRemoveAllDataFile RemoveAllDataFile = (funcRemoveAllDataFile)GetProcAddress(hDLL, "RemoveAllDataFile");
    if (RemoveAllDataFile)
    {
        return 2;
    }
    else
    {
        return 1;
    }

}

4

2 回答 2

1

extern "C"如果使用 C++ 源代码,则应声明从其他 DLL 导出的函数。如果应该使用.def文件或使用导出__declspec(dllexport)

这是一个典型的 DLL 头文件,它适用于.c.cpp两种调用约定:

#ifdef MYAPI_EXPORTS
#define MYAPI __declspec(dllexport)
#else
#define MYAPI __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif

MYAPI int __cdecl   func1(int x);
MYAPI int __stdcall func2(int x);

#ifdef __cplusplus
}
#endif

DLL 源:

#define MYAPI_EXPORTS
#include "x.h"
int func1(int x)
{
    return x*2;
}

int __stdcall func2(int x)
{
    return x*3;
}

和用法:

#include <windows.h>
#include <stdio.h>

typedef int (__cdecl   *FUNC1)(int);
typedef int (__stdcall *FUNC2)(int);
int main()
{

    HINSTANCE hDLL = LoadLibrary("x");
    FUNC1 func1 = (FUNC1)GetProcAddress(hDLL, "func1");
#ifdef _WIN64
    FUNC2 func2 = (FUNC2)GetProcAddress(hDLL, "func2");
#else
    FUNC2 func2 = (FUNC2)GetProcAddress(hDLL, "_func2@4");
#endif
    printf("%d %d\n",func1(5),func2(5));
}

名称装饰可以用dumpbin /exports <dll>. 请注意,x64 和 x86 不同。以下是针对 x86 的:

   ordinal hint RVA      name

         2    0 00001010 _func2@4
         1    1 00001000 func1
于 2015-02-16T18:32:01.733 回答
0

查看 DLL 的实际导出,例如使用 TDUMP 或类似的报告工具。您正在寻找的功能没有"RemoveAllDataFile"像您期望的那样被导出。它实际上是被导出的"_RemoveAllDataFile",甚至像"_RemoveAllDataFile@4".

如果您正在编译原始 DLL,并希望将函数导出为"RemoveAllDataFile",则必须将导出函数的声明包装为 ,extern "C"以从导出的名称中删除任何 C++ 名称修饰。根据您的 C++ 编译器,您可能还需要使用文件来删除调用约定.def强加的前导下划线。__cdecl使用 C 链接时,一些 C++ 编译器导出__cdecl函数时带有前导下划线(例如 Borland),而有些则不导出(例如 Microsoft)。

但是,如果您不重新编译原始 DLL,那么您别无选择,只能查看 DLL 的导出并更改GetProcAddress()调用以使用实际导出的正确名称。

于 2015-02-16T18:29:18.587 回答