我试图为一个dll导出一个简单的测试函数来使用一个应用程序(fyi:mIRC),它将调用约定指定为:
int __stdcall test_func(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause)
现在,要从应用程序中调用它,我将使用 test_func 但我注意到由于名称错误,它并不像我想象的那么简单 .
通过类似的主题,我已经了解到将 extern "C" 与 __declspec(dllexport) 结合使用是一种等效的(某种程度上)方法,可以去除对模块定义(.def)的修改 . 但是,当使用extern / dllexport方法时,我的函数(作为示例)始终是 _test_func@numbers ,而.def删除了所需的所有修改,以便与我需要导出的应用程序一起使用 .
有人可以解释一下这是为什么吗?我只是对这两种方法感到好奇 . 谢谢!
2 回答
dllexport / import设计为自己加载,而不是使用GetProcAddress的旧C库 . 您看到的错误是所有Microsoft编译器长期为__stdcall函数所做的事情 . 最有可能的是,你的目标要求__cdecl函数,而不是__stdcall,但如果没有,你需要使用.def文件来专门解除名称 .
extern "C"
与stdcall无关:它只声明C名称修改(也称为类型安全链接;在符号名称中包含类型信息)是禁用的 . 无论是使用C调用约定还是使用stdcall调用约定,都需要使用它 .在stdcall调用约定中,被调用者从堆栈中删除参数 . 为了安全起见,导出的名称包含被调用者将从堆栈中删除的字节数 .
如果要导出的应用程序要求不在名称中添加
@number
后缀,则可能意味着它需要C调用约定 . 所以你应该停止将该函数声明为__stdcall
. 当您将其声明为declspec(dllexport)
时,您应该在DLL中获得未修饰的名称 .在DEF文件中,您可以随意调用该函数;没有进行额外的检查 .