使用 extern c 和 dllexport 与模块定义进行 stdcall 名称修改 (msvc++)
我试图为 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 删除了与我需要导出到的应用程序一起使用所需的所有损坏。
有人可以解释一下这是为什么吗?我只是对这两种方法感到好奇。谢谢!
I was trying to export a simple test function for a dll to work with an application (fyi: mIRC) that specifies the calling convention as:
int __stdcall test_func(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause)
Now, to call this from the application, I'd be using test_func but I have noticed due to name mangling it is not as simple as I'd thought.
Through similar topics here I have come to the understanding that using extern "C" in combination with __declspec(dllexport) is an equivelant (somewhat) method of removing mangling to module definitions (.def). However, when using the extern/dllexport method my function (as an example) is always _test_func@numbers whereas the .def removed all mangling as required for use with the application i needed to export to.
Could someone please explain why this is? I'm just curious about the two methods. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
extern "C"
与 stdcall 无关:它仅声明禁用 C++ 名称修改(又名类型安全链接;在符号名称中包含类型信息)。无论您使用 C 调用约定还是 stdcall 调用约定,您都需要使用它。在 stdcall 调用约定中,被调用者从堆栈中删除参数。为了确保安全,导出的名称包含被调用者将从堆栈中删除的字节数。
如果您要导出到的应用程序要求名称中不添加
@number
后缀,则可能意味着它需要 C 调用约定。因此,您应该停止将函数声明为__stdcall
。当您将其声明为declspec(dllexport)
时,您应该在 DLL 中获得一个未修饰的名称。在DEF文件中,你可以随意调用该函数;不执行任何额外检查。
extern "C"
has nothing to do with stdcall: it only declares that C++ name mangling (aka type-safe linkage; inclusion of type information in symbol name) is disable. You need to use it independent of whether you use C calling convention or stdcall calling convention.In stdcall calling convention, the callee removes the parameters from the stack. To make that safe, the exported name contains the number of bytes that the callee will remove from the stack.
If the application you are exporting to requires that no
@number
suffix is added to the name, it probably means that it expects C calling convention. So you should stop declaring the function as__stdcall
. When you the declare it asdeclspec(dllexport)
, you should get an undecorated name in the DLL.In the DEF file, you can call the function whatever you want; no additional checking is performed.
dllexport/import 被设计为自行加载,而不是使用 GetProcAddress 的旧 C 库。您所看到的重整是所有 Microsoft 编译器长期以来对 __stdcall 函数所做的事情。最有可能的是,您的目标需要 __cdecl 函数,而不是 __stdcall,但如果不是,您将需要使用 .def 文件来专门取消名称的破坏。
dllexport/import are designed to be loaded back by themselves, not an old C library using GetProcAddress. The mangling you have seen is what all Microsoft compilers have done for a long time for __stdcall functions. Most likely, your target either expects a __cdecl function, not __stdcall, but if not, you will need to use a .def file to specifically un-mangle the name.