我正在使用 MinGW-w64 并尝试使用 GetProcAddress 从 DLL 动态导入函数。我要导入的函数具有以下签名:
__declspec(dllexport) double __cdecl func(double t, unsigned int n);
要检索该函数,我使用 WIN32 API 中的 GetProcAddress,如下所示:
typedef double (__cdecl *TYPE_FUNCTION)(double, unsigned int);
TYPE_FUNCTION func_ptr = (TYPE_FUNCTION) GetProcAddress(hinstLib, "func");
但是,我收到以下信息:
warning: cast between incompatible function types from 'FARPROC' {aka 'long long int (*)()'} to 'double (*)(double, unsigned int)'
我应该担心这个警告吗?如果是这样,我如何安全地转换或调用该函数?转换会在运行时造成任何潜在的问题吗?
使用
__declspec(dllimport) double __cdecl func(double t, unsigned int n);
和
PVOID __imp_func;
(如果 c++ 声明两者为
EXTERN_C
或 extern "C"
)
最后
__imp_func = GetProcAddress(hinstLib, "func");
所以我们不需要任何
typedef
和 cast
说明:
当我们使用
func
属性声明函数 __declspec(dllimport)
时,编译器会在修饰函数 extern PVOID __imp_func;
名称中声明变量 __imp_
(添加 func
)前缀。当你调用 func
编译器生成代码 call __imp_func
;所以我们需要的一切 - 实施PVOID __imp_func;
。如果是静态链接 - __imp_func
将位于某个 lib 文件内。如果您使用动态链接 - 只需自行实现 PVOID __imp_func;
(不带 extern
)并从 GetProcAddress
(或 LdrGetProcedureAddress
)为其分配值。注意 - 这是针对 x64 修改的。对于 x86,这将是 _imp__func
(因为 __cdecl
- func
将转换为 _func
)
如果使用 __stdcall
- 将是 __imp__func@8
。我们不能声明
已经PVOID __imp__func@8;
了。但我们可以使用 asm
来实现这一点。或者如果使用 CL(更名为 msvc)编译器(最新版本),我们可以使用
__identifier
关键字与
#pragma warning(disable: 4483) // Allow use of __identifier
所以代码在 x86 情况下并且 api 是
__stdcall
#pragma warning(disable: 4483) // Allow use of __identifier
__declspec(dllimport) double __stdcall func(double t, unsigned int n);
#define __imp_func __identifier("_imp__func@8")
PVOID __imp_func; // = GetProcAddress(hinstLib, "func");