C DLL 导出:修饰/损坏的名称

新手上路,请多包涵

使用模块定义文件 (MyDLL.def) 创建基本 C++ DLL 和导出名称。编译后,我使用 dumpbin.exe 检查导出的函数名称,我希望看到:

 SomeFunction

但我看到的是:

 SomeFunction = SomeFunction@@@23mangledstuff#@@@@

为什么?

导出的函数看起来没有修饰(特别是与不使用 Module Def 文件相比),但其他的东西怎么了?

如果我对来自任何商业应用程序的 DLL 使用 dumpbin.exe ,你就会得到干净的:

 SomeFunction

没有别的…

我还尝试删除模块定义并使用导出的“C”样式导出名称,即:

 extern "C" void __declspec(dllexport) SomeFunction();

(仅使用“extern”C”并没有创建导出函数)

但是,这仍然会产生相同的输出,即:

 SomeFunction = SomeFunction@@@23mangledstuff#@@@@

我还尝试了 #define dllexport __declspec(dllexport) 选项并创建了一个没有问题的 LIB。但是,我不想向在 C# 应用程序中使用 DLL 的人提供 LIB 文件。

它是一个普通的 C++ DLL(非托管代码),只用 C++ 编译,只是一个简单的头文件和代码。如果没有 Module Def,我会得到损坏的导出函数(我可以创建一个静态库并使用 LIB 没问题。我试图避免这种情况)。如果我使用 extern "C" __declspec(dllexport) 模块定义,我会得到一个似乎未修饰的函数名称……唯一的问题是它后面跟着一个“=”,看起来像是函数的修饰版本.我想摆脱“=”之后的东西 - 或者至少了解它为什么存在。

就目前而言,我很确定我可以使用 P/Invoke 从 C# 调用该函数……我只是想避免在“=”末尾出现垃圾。

我愿意接受有关如何更改项目/编译器设置的建议,但我只是使用了标准的 Visual Studio DLL 模板——没什么特别的。

原文由 Bob 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 830
2 个回答

您可以通过关闭调试信息生成来获得所需的内容。项目 + 属性、链接器、调试、生成调试信息 = 否。

自然,您只想为发布版本执行此操作。选项已经以这种方式设置的地方。

原文由 Hans Passant 发布,翻译遵循 CC BY-SA 2.5 许可协议

我知道有多少次我尝试使用代码和#pragma 强制函数名称。而且我总是以完全相同的方式结束,最后使用模块定义文件 (*.def)。原因如下:

 //---------------------------------------------------------------------------------------------------
// Test cases built using VC2010 - Win32 - Debug / Release << doesn't matter
//---------------------------------------------------------------------------------------------------
// SET: Project > Properties > Linker > Debugging > Generate Debug Info = Yes (/DEBUG)
//  || (or, also doesn't matter)
// SET: Project > Properties > Linker > Debugging > Generate Debug Info = No + delete PDB file!

extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback

extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> _SetCallback@4

__declspec(dllexport) void SetCallback(LPCALLBACK function);
> ?SetCallback@@YAXP6AXHPADPAX@Z@Z

__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> ?SetCallback@@YGXP6GXHPADPAX@Z@Z

//---------------------------------------------------------------------------------------------------
// this also big is nonsense cause as soon you change your calling convention or add / remove
// extern "C" code won't link anymore.

// doesn't work on other cases
#pragma comment(linker, "/EXPORT:SetCallback")
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);

// doesn't work on other cases
#pragma comment(linker, "/EXPORT:SetCallback=SetCallback")
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);

// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=_SetCallback@4")
extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);

// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=?SetCallback@@YAXP6AXHPADPAX@Z@Z")
__declspec(dllexport) void SetCallback(LPCALLBACK function);

// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=?SetCallback@@YGXP6GXHPADPAX@Z@Z")
__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);

//---------------------------------------------------------------------------------------------------
// So far only repetable case is using Module-Definition File (*.def) in all possible cases:
EXPORTS
  SetCallback

extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback

extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> SetCallback

__declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback

__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> SetCallback

// And by far this is most acceptable as it will reproduce exactly same exported function name
// using most common compilers. Header is dictating calling convention so not much trouble for
// other sw/ppl trying to build Interop or similar.

我想知道为什么没有人这样做,我只花了 10 分钟来测试所有案例。

原文由 SoLaR 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题