在C中呼叫公约名称管理

时间:2014-12-15 15:43:41

标签: c visual-c++

我问的不是如何禁用C ++名称修改(我知道它的外部" c")。问题不在于C ++

据我所知,当我将一个函数声明为__stdcall时,它的名称应该像_FuncName @ 8中那样被破坏(对于两个int参数)。当我将一个函数声明为__cdecl时,它应该像_FuncName一样被修改。

听起来很好,但它真的像这样吗?

有两种情况我不明白:

1-)我在vc ++ 2013中制作了一个dll而我在__cdecl函数上使用了__declspec(dllexport)。它的导出没有任何下划线(只是FuncName)。我没有.def文件或任何内容,也没有使用pragma export。

2-)大多数Windows API函数都是__stdcall。但他们没有_或@。例如,它们像MessageBoxA一样导出,没有任何损坏。

那怎么解释呢?

1 个答案:

答案 0 :(得分:1)

是的,Visual C ++将name decoration添加到C符号导出,以及C ++导出的名称修改。您可以在每个调用约定关键字的主题中阅读MSDN上的名称修饰约定。 extern "C"链接规范实际上将导出的符号从C ++名称修改切换到C名称修饰,这会不时给人们带来惊喜。

因此,对于导出函数的C文件,如果您非常非常仔细地阅读MSDN上__cdecl的文档,那么您会看到它提到" Underscore字符(_)以名称为前缀,除非导出使用C链接的__cdecl函数。"这仍然不是很清楚,因为"导出"这里指的是DLL导出,它也适用于非功能符号,如导出数据。这是您在自己的代码中看到的内容。

我的猜测是这些名称是未修饰的DLL导出,以便使语言互操作容易。您会注意到链接符号名称导出仍然具有前导下划线,如果您转储.lib文件的导出,则可以看到。

对于第二种情况,使用.def文件使用特定名称导出__stdcall Windows API函数。这就是如何获得映射到API的窄字符和宽字符版本的默认名称。您可以使用#pragma comment(linker, "/export:alias=_original")获得相同的效果,但使用.def文件方法可能是最便携的。

您可以在Raymond Chen的 The history of calling conventions 博客上找到关于The Old New Thing的故事。