15

我试图为 dll 导出一个简单的测试函数,以便与将调用约定指定为的应用程序(仅供参考: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 删除了所有需要与我需要导出到的应用程序一起使用的修改。

有人可以解释这是为什么吗?我只是对这两种方法感到好奇。谢谢!

4

2 回答 2

15

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

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

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

在 DEF 文件中,你可以随意调用函数;不执行额外的检查。

于 2010-12-28T23:40:35.483 回答
13

dllexport/import 旨在自行加载,而不是使用 GetProcAddress 的旧 C 库。您看到的修改是所有 Microsoft 编译器长期以来对 __stdcall 函数所做的事情。最有可能的是,您的目标需要一个 __cdecl 函数,而不是 __stdcall,但如果没有,您将需要使用 .def 文件来专门解开名称。

于 2010-12-28T23:44:33.560 回答