创建基本的C++DLL和出口的名称使用定义模块文件(MyDLL.def).编译之后我检查了出口功能名称的使用 dumpbin.exe 我希望看到:

SomeFunction

但我看到这个:

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

为什么?

出口的功能会出现未修饰(尤其是相对于不使用模块Def文件),但为什么其他的东西?

如果我用 dumpbin.exe 对DLL从任何商业应用程序,你获得清洁:

SomeFunction

并没有别的...

我也试着去除模块的定义和出口的名称中使用"C"的风格的出口,即:

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

(简单地使用"外部"C"没有创造一个出口功能)

然而,这仍然造成相同的输出,即:

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

我也试过 #define dllexport __declspec(dllexport) 选项并创建了一个LIB没有问题。然而,我不想要必须提供一个LIB文件的人使用DLL在他们C#应用程序。

这是一个普通的香草C++DLL(管理的代码),编制用C++不过是一个简单的标题和编码。没有模块Def我错位的出口功能(我可以创建一个静态的图书馆和使用LIB没有问题。我试着避免那)。如果我用 extern "C" __declspec(dllexport) 模块的定义,我得到了什么似乎是一个未装饰功能的名字...唯一的问题是,它是随后通过一个"="和什么看起来像一个装饰版本的功能。我想要摆脱的东西之后的"="-或至少理解为什么它是存在的。

因为它的立场,我敢肯定,我可以打电话的功能,从C#用P/援引...我只是想避免这种垃圾在结束"=".

我很开放的建议如何改变该项目的/编译器的设置,但是,我只是用标准Visual Studio DLL模板-没有什么特别的。

有帮助吗?

解决方案

你可以得到你想要什么通过关闭"调试"的信息的产生。项目+性、连接器,调试,产生"调试"的信息=没有。

当然,你只想要这样做对于释放建设。那里的选择是已经设置这种方式。

其他提示

而不是使用。def文件只是插入 pragma comment 像这样的

#pragma comment(linker, "/EXPORT:SomeFunction=_SomeFunction@@@23mangledstuff#@@@@")

编辑:或甚至更加容易:身体内部的功能使用

#pragma comment(linker, "/EXPORT:"__FUNCTION__"="__FUNCDNAME__)

...如果你有麻烦找到装饰职能名称。这最后一批注可以进一步减少用一个简单的宏观定义。

你必须要声明的功能 extern "C" 如果你不想要他们的名字被损坏。

从经验看,要小心,如果您使用 __stdcall 在您的签名。与 __stdcall, ,名称仍将是错位的某种程度上(你将迅速找出足够的).显然,有两个级别的重整,其中一个 extern "C" 交易与至C++的水平,但它不处理与另一个级别的名称重整造成的 __stdcall.额外重整显然是有关超载的--但我并不肯定这一点。

对不起,对于在回答一个旧线,但是已被标记为答案并没有为我工作。

作为一个人数有所指出的,外部的"C"装饰是很重要的。改变"项目的/特性/连接/调试"/"产生"调试"的信息"的设定作出绝对没有任何差错位的名称正在产生的对我来说在"调试"或释放建设模式。

设置:VS2005编制一些用C++类库项目。我检查汇编。dll输出与微软的依赖Walker工具。

这里是一个例子配方,为我工作...

在项目。h:

#define DllExport extern "C" __declspec( dllexport )

DllExport bool API_Init();
DllExport bool API_Shutdown();

在project.cpp:

#include "project.h"

bool API_Init()
{
  return true;
}

bool API_Shutdown()
{
  return true;
}

然后被称为从C#管理的代码、类。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();
    }
}

做上述防止的错位的名称,在调试和释放模式,不论产生"调试"的信息设定。好运气。

即使没有重整,32位和64位建立名称的出口不同,甚至与外部"C"。看看DEPENDS.EXE.

这可能意味着大麻烦到任何客户,并一LoadLibrary+GetProcAdress来访问您的功能。

因此,在所有其他人使用一个模块的定义文件如下:

LIBRARY MYDLL
EXPORTS
myFunction=myFunction

叶氏,这一点痛苦保持,但随后有多少出口功能做你写的一天?

此外,我通常变化的宏如下文所示,自从我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);

最后一行中使用的混淆VisualAssistX几年前,我不知道,如果它恰当地的摘要,它现在:-)

我知道有多少次我试图迫使职能名称的使用代码和编译。我始终端用完全同样的事情,采用模块定义的文件(*.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分钟,以测试所有情况。

该SomeFunction@@@23mangledstuff#@@@@出错得到的类型和类的C++的功能。简单的出口功能,是可调用从C即都写在C,或者是宣布的外部"C'C++编码。如果是你想要一个简单的接口,你必须做的功能,你的出口能使用只是C类型和使非成员能在全球名称空间。

基本上,当你用功能在C++、零件他们的名字现在包括他们的签名等等,以促进语言的功能,像超载。

如果你写一DLL使用声明影响(dllexport),那么它还应产生一个lib。链接,lib,你会被自动链接的功能登记的通过CRT在启动时间(如果你想起了以改变你的所有进口,出口品)。你不需要知道名字重整的,如果你用这个系统。

在情况下,它不清楚从数百行的华夫饼的主题上的错位的出口。这是我2c值:)

在创建一个项目称为Win32Project2使用VS2012年选出所有的符号中的向导。你应该有2个所谓的文件Win32Project2.cpp 和Win32project2.h

这些将参考一个例子可供出口的变量和一个例子出口的功能。

在Win32Project2.h你会有以下几种:

#ifdef WIN32PROJECT2_EXPORTS
#define WIN32PROJECT2_API __declspec(dllexport)
#else
#define WIN32PROJECT2_API __declspec(dllimport)
#endif

extern WIN32PROJECT2_API int nWin32Project2;
WIN32PROJECT2_API int fnWin32Project2(void);

到unmangle改变的最后两行到外部"C"声明:

extern "C" WIN32PROJECT2_API int nWin32Project2;
extern "C" WIN32PROJECT2_API int fnWin32Project2(void);

在Win32Project2.cpp 你还会有以下默认的定义:

// This is an example of an exported variable
WIN32PROJECT2_API int nWin32Project2=0;

// This is an example of an exported function.
WIN32PROJECT2_API int fnWin32Project2(void)
{
    return 42;
}

到unmangle这些更改为:

// This is an example of an exported variable
extern "C" WIN32PROJECT2_API int nWin32Project2=0;

// This is an example of an exported function.
extern "C" WIN32PROJECT2_API int fnWin32Project2(void)
{
    return 42;
}

基本上必须使用外部"C"前缀以前的声明,以便力的连接产生unmangled C喜欢的名字。

如果你喜欢使用改变后的姓名,为这些额外的混淆(情况下的重整的信息是有用的人以某种方式)使用"dumpbin/出口Win32Project2.dll"从VC命令行查找实际参考的名字。它将具有的形式"?fnWind32Project2@[param字节]@[其他信息].还有其他DLL视的工具,如果在运行一个VC命令不浮动你的船。

为什么毫不默认该公约是一个谜。实际重整的信息意味着什么(如参数字节的大小和更多的),这可能会有助于验证和调试,但是其他的废话.

进口DLL函数以上为C#项目(在这种情况下,一个基本的C#windows的应用程序形式上的,它包含的按钮"button1")这里的一些样品代号:

using System.Runtime.InteropServices;



    namespace AudioRecApp
    {

      public partial class Form1 : Form
      {
        [ DllImport("c:\\Projects\test\Debug\Win32Projects2.dll")] 
        public static extern int fnWin32Project2();

        public Form1()
        {
          InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)
        {
          int value;

          value = fnWin32Project2();
        }
      }
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top