在 C++ 中创建 DLL 以在 VS 2005 中导入 C++ DLL
Creating a DLL in C++ to import C++ DLL in VS 2005
我正在尝试 link C++ DLL 到我将创建的新 C++ DLL,
我已经按照下面的教程和许多其他教程一步一步地进行了操作,但是 "GetProcAddress" 函数 returns NULL "http://www.dreamincode.net/forums/topic/118076-dlls-explicit-linking/"
出了点问题
这是我尝试从 DLL 调用的函数的原型:
int RemoveAllDataFile( unsigned int id );
函数 returns 为 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;
}
}
查看 DLL 的实际导出,例如使用 TDUMP 或类似的报告工具。您要查找的函数未像您期望的那样导出为 "RemoveAllDataFile"
。它实际上被导出为 "_RemoveAllDataFile"
,甚至是 "_RemoveAllDataFile@4"
.
如果您正在编译原始 DLL,并希望将函数导出为 "RemoveAllDataFile"
,则必须用 extern "C"
包装导出函数的声明,以从导出名称。根据您的 C++ 编译器,您可能还需要使用 .def
文件来删除 __cdecl
调用约定强加的前导下划线。使用 C 链接时,一些 C++ 编译器导出带有前导下划线的 __cdecl
函数(例如 Borland),而有些则不导出(例如 Microsoft)。
但是如果您不重新编译原始 DLL,那么您别无选择,只能查看 DLL 的导出并更改 GetProcAddress()
调用以使用实际导出的正确名称。
如果使用 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
我正在尝试 link C++ DLL 到我将创建的新 C++ DLL,
我已经按照下面的教程和许多其他教程一步一步地进行了操作,但是 "GetProcAddress" 函数 returns NULL "http://www.dreamincode.net/forums/topic/118076-dlls-explicit-linking/"
出了点问题这是我尝试从 DLL 调用的函数的原型:
int RemoveAllDataFile( unsigned int id );
函数 returns 为 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;
}
}
查看 DLL 的实际导出,例如使用 TDUMP 或类似的报告工具。您要查找的函数未像您期望的那样导出为 "RemoveAllDataFile"
。它实际上被导出为 "_RemoveAllDataFile"
,甚至是 "_RemoveAllDataFile@4"
.
如果您正在编译原始 DLL,并希望将函数导出为 "RemoveAllDataFile"
,则必须用 extern "C"
包装导出函数的声明,以从导出名称。根据您的 C++ 编译器,您可能还需要使用 .def
文件来删除 __cdecl
调用约定强加的前导下划线。使用 C 链接时,一些 C++ 编译器导出带有前导下划线的 __cdecl
函数(例如 Borland),而有些则不导出(例如 Microsoft)。
但是如果您不重新编译原始 DLL,那么您别无选择,只能查看 DLL 的导出并更改 GetProcAddress()
调用以使用实际导出的正确名称。
如果使用 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