而不是声明变量
int (__stdcall *pRandomNumber)(size_t cb, unsigned char *pb);
您可以使用__declspec(dllimport)
属性和使用[[nodiscard]]
和/或_Must_inspect_result_
在此声明上声明函数
EXTERN_C
_NODISCARD
DECLSPEC_IMPORT
_Must_inspect_result_
int
WINAPI
RandomNumber(
_In_ size_t cb,
_Out_writes_bytes_(cb) unsigned char *pb
);
在内部,当你用__declspec(dllimport)
属性声明 api 时,编译器用关键字声明 变量;extern
extern "C" {
extern PVOID __imp_<function_name>;
}
in place <function_name> __FUNCDNAME__
used - 函数的修饰名称
所以可能说和
extern PVOID __imp_##__FUNCDNAME__;
当然,因为extern,这只是声明。如果你不添加定义 - 你得到了
error LNK2001: unresolved external symbol __imp_RandomNumber
如果你尝试打电话RandomNumber
。所以你需要添加定义。因为_AMD64_
这很简单,因为extern "C"
符号没有装饰。
所以简单地写:
EXTERN_C_START
PVOID __imp_RandomNumber;
EXTERN_C_END
反而
EXTERN_C_START
int (__stdcall *pRandomNumber)(size_t cb, unsigned char *pb);
EXTERN_C_END
在这两种情况下,您都需要声明指针大小变量,它将保存函数指针-仅在名称上不同-您选择pRandomNumber
名称(并且可以选择任何名称)-在我的情况下-您必须选择__imp_RandomNumber
(__imp_<function_name>
)-为修饰的函数名称添加__imp_
前缀.
但如果_X86_
存在问题 - 对于__stdcall
- @符号将在修饰函数名称中。你需要写
EXTERN_C_START
PVOID __imp__RandomNumber@8;
EXTERN_C_END
因为装饰名称将是_RandomNumber@8
. 但__imp__RandomNumber@8
不是有效的c/c++名称。您可以在 asm 代码中定义这样的名称,但不能在c/c++中定义。但您可以使用/alternatename
链接器选项。
__pragma(comment(linker, "/alternatename:__imp__RandomNumber@8=___imp_RandomNumber"))
EXTERN_C_START
PVOID __imp_RandomNumber;
EXTERN_C_END
如果未找到链接器,请__imp__RandomNumber@8
尝试使用___imp_RandomNumber
(如果存在)。并将__imp_RandomNumber
被装饰___imp_RandomNumber
到_X86_
可能写下一个宏
#ifdef _X86_
#define ALT_NAME(name, n) __pragma(comment(linker, _CRT_STRINGIZE(/alternatename:__imp__##name##@##n####=___imp_##name)))
#else
#define ALT_NAME(name, n)
#endif
#define IMP_FUNC(name, n) EXTERN_C_START PVOID __imp_##name; EXTERN_C_END ALT_NAME(name, n)
有了这个你的代码将是
// global declaration
EXTERN_C
_NODISCARD
DECLSPEC_IMPORT
_Must_inspect_result_
int
WINAPI
RandomNumber(
_In_ size_t cb,
_Out_writes_bytes_(cb) unsigned char *pb
);
IMP_FUNC(RandomNumber, 8);
// initialization
__imp_RandomNumber = GetProcAddress(GetModuleHandle(L"foo"), "RandomNumber");
//usage
if (__imp_RandomNumber )
{
UCHAR test[16];
RandomNumber(sizeof(test), test);
}
你得到了
warning C4834: discarding return value of function with 'nodiscard' attribute
如果不使用返回值RandomNumber