首页 文章

使用extern c和dllexport vs模块定义(msvc)的stdcall名称修改

提问于
浏览
15

我试图为一个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 回答

  • 12

    dllexport / import设计为自己加载,而不是使用GetProcAddress的旧C库 . 您看到的错误是所有Microsoft编译器长期为__stdcall函数所做的事情 . 最有可能的是,你的目标要求__cdecl函数,而不是__stdcall,但如果没有,你需要使用.def文件来专门解除名称 .

  • 12

    extern "C" 与stdcall无关:它只声明C名称修改(也称为类型安全链接;在符号名称中包含类型信息)是禁用的 . 无论是使用C调用约定还是使用stdcall调用约定,都需要使用它 .

    在stdcall调用约定中,被调用者从堆栈中删除参数 . 为了安全起见,导出的名称包含被调用者将从堆栈中删除的字节数 .

    如果要导出的应用程序要求不在名称中添加 @number 后缀,则可能意味着它需要C调用约定 . 所以你应该停止将该函数声明为 __stdcall . 当您将其声明为 declspec(dllexport) 时,您应该在DLL中获得未修饰的名称 .

    在DEF文件中,您可以随意调用该函数;没有进行额外的检查 .

相关问题