用C ++创建DLL以在VS 2005中导入C ++ DLL

时间:2015-02-16 18:24:23

标签: c++ dll dllimport getprocaddress

我正在尝试将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;
    }

}

2 个答案:

答案 0 :(得分:1)

如果使用C ++源,则应从另一个DLL导出的函数声明为extern "C"。如果应使用.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

答案 1 :(得分:0)

查看DLL的实际导出,例如使用TDUMP等报告工具。您正在寻找的功能不会像您期望的那样导出为"RemoveAllDataFile"。它实际上是像"_RemoveAllDataFile"一样导出,甚至是"_RemoveAllDataFile@4"

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

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