Bob*_*Bob 26 c++ dll export name-decoration
使用模块定义文件(MyDLL.def)创建基本C++ DLL和导出的名称.编译后我检查导出的函数名称,dumpbin.exe
我希望看到:
SomeFunction
Run Code Online (Sandbox Code Playgroud)
但我看到了这一点:
SomeFunction = SomeFunction@@@23mangledstuff#@@@@
Run Code Online (Sandbox Code Playgroud)
为什么?
导出的函数显示为未修饰(特别是与不使用Module Def文件相比),但其他内容是什么?
如果我使用dumpbin.exe来自任何商业应用程序的DLL,你会得到干净的:
SomeFunction
Run Code Online (Sandbox Code Playgroud)
没有别的......
我还尝试删除模块定义并使用"C"导出方式导出名称,即:
extern "C" void __declspec(dllexport) SomeFunction();
Run Code Online (Sandbox Code Playgroud)
(简单地使用"extern"C"没有创建导出函数)
但是,这仍然会产生相同的输出,即:
SomeFunction = SomeFunction@@@23mangledstuff#@@@@
Run Code Online (Sandbox Code Playgroud)
我也尝试了这个#define dllexport __declspec(dllexport)选项并创建了一个没有问题的LIB.但是,我不想在他们的C#应用程序中向使用DLL的人提供LIB文件.
它是一个普通的C++ DLL(非托管代码),用C++编译,只是一个简单的头和代码.没有Module Def我得到了错误的导出函数(我可以创建一个静态库并使用LIB没问题.我试图避免这种情况).如果我使用extern "C" __declspec(dllexport) OR模块定义我得到的似乎是一个未修饰的函数名...唯一的问题是它后跟一个"=",看起来像是函数的装饰版本.我想摆脱"="之后的东西 - 或者至少理解它为什么存在.
既然这样,我敢肯定,我可以使用P调用从C#中的函数/调用...我只是想避免垃圾在"="号结束.
我对如何更改项目/编译器设置的建议持开放态度,但我只使用了标准的Visual Studio DLL模板 - 没什么特别的.
wqw*_*wqw 40
而不是使用.def文件只是pragma comment像这样插入
#pragma comment(linker, "/EXPORT:SomeFunction=_SomeFunction@@@23mangledstuff#@@@@")
Run Code Online (Sandbox Code Playgroud)
编辑:甚至更容易:在函数体内使用
#pragma comment(linker, "/EXPORT:"__FUNCTION__"="__FUNCDNAME__)
Run Code Online (Sandbox Code Playgroud)
...如果你找到装饰的功能名称有麻烦.使用简单的宏定义可以进一步减少最后一个pragma.
Han*_*ant 16
您可以通过关闭调试信息生成来获得所需的内容.项目+属性,链接器,调试,生成调试信息=否.
当然,您只想为Release版本执行此操作.选项已经设置的位置.
小智 11
根据经验,如果您__stdcall在功能签名中使用,请务必小心.有了__stdcall,名称将在某种程度上受损(你会发现很快).显然,有两个级别的修改,一个是extern "C"C++级别的处理,但它不涉及由另一个级别的名称修改引起的__stdcall.额外的重整显然与超载相关 - 但我不确定.
很抱歉回复旧帖子,但标记为答案的内容对我不起作用.
正如一些人所指出的那样,外部的"C"装饰很重要.更改"项目/属性/链接器/调试/生成调试信息"设置对于在调试或发布构建模式下为我生成的错位名称完全没有区别.
安装程序:VS2005编译Visual C++类库项目.我正在使用Microsoft的Dependency Walker工具检查已编译的.dll输出.
这是一个适合我的示例配方......
在project.h中:
#define DllExport extern "C" __declspec( dllexport )
DllExport bool API_Init();
DllExport bool API_Shutdown();
Run Code Online (Sandbox Code Playgroud)
在project.cpp中:
#include "project.h"
bool API_Init()
{
return true;
}
bool API_Shutdown()
{
return true;
}
Run Code Online (Sandbox Code Playgroud)
然后从C#托管代码调用class.cs:
using System.Runtime.Interopservices;
namespace Foo
{
public class Project
{
[DllImport("project.dll")]
public static extern bool API_Init();
[DllImport("project.dll")]
public static extern bool API_Shutdown();
}
}
Run Code Online (Sandbox Code Playgroud)
无论生成调试信息设置如何,执行上述操作都会在调试和释放模式下防止出现损坏的名称.祝好运.
小智 5
即使没有修改,32位和64位版本的名称输出也不同,即使使用extern"C"也是如此.使用DEPENDS.EXE查看它.
对于任何执行LoadLibrary + GetProcAdress访问您的功能的客户来说,这可能意味着很大的麻烦.
因此,除了所有其他人之外,还使用模块定义文件,如下所示:
LIBRARY MYDLL
EXPORTS
myFunction=myFunction
Run Code Online (Sandbox Code Playgroud)
是的,维护起来有点痛苦,但是你每天写出多少导出函数?
此外,我通常更改如下所示的宏,因为我的DLL导出函数不是C++类,我希望它们可以被大多数编程环境调用:
#ifdef WTS_EXPORTS
#define WTS_API(ReturnType) extern "C" __declspec(dllexport) ReturnType WINAPI
#else
#define WTS_API(ReturnType) extern "C" __declspec(dllimport) ReturnType WINAPI
#endif
WTS_API(int) fnWTS(void);
Run Code Online (Sandbox Code Playgroud)
几年前用于混淆VisualAssistX的最后一行,我不知道它现在是否正确消化它:-)
我知道我尝试过多少次使用代码和#pragma's 来强制函数名称。而且我总是以完全相同的方式结束,最后使用模块定义文件 (*.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.
Run Code Online (Sandbox Code Playgroud)
我想知道为什么没有人这样做,我只花了 10 分钟就测试了所有案例。
| 归档时间: |
|
| 查看次数: |
49314 次 |
| 最近记录: |