1

我在 MV C++ 2012 中创建了一个 DLL,当我使用

Dumpbin /Exports filename

DLL 文件中的函数名称内部有一个等号。我不得不使用公共语言运行时支持 (/crl),因为我使用了 C# 中的 DLL。这就是为什么函数的名称会显示等号的原因吗?我的头文件:

#ifdef ColorDLL_EXPORTS
#define ColorDLL_API __declspec(dllexport)
#else
#define ColorDLL_API __declspec(dllexport)
#endif

extern "C"{
ColorDLL_API int ColorSelect(int i);
}

颜色DLL.cpp

#include "stdafx.h"
#include "ColorDLL.h"
#using <ColorDiologeClass.dll>

extern "C"{
ColorDLL_API int ColorSelect(){
ColorDiologeClass::Class1::ColorReturn(1);
return 1;
}

当我使用 Dumpbin 时,名称显示如下:

Name
ColorSelect = _ColorSelect

为什么是这样?我希望它显示为 ColorSelect,而不是 ColorSelect = _ColorSelect。如果我这样离开它,我将如何从需要确切函数名称的 JMP 之类的程序中调用此函数?会是 ColorSelect 吗?还是 ColorSelect = _ColorSelect?

4

3 回答 3

0

名称是“mangled”——返回类型和参数被嵌入到函数的名称中。如果您不希望这样,您可以extern "C"在函数名之前使用(或在函数块周围)。

于 2013-05-31T22:27:08.433 回答
0

那就是名称修饰,这是 c++ 的底层特性,它允许它支持函数重载(因为它将函数的参数类型合并到它的名称中)。

这是另一个更详细的问题。

于 2013-05-31T22:27:42.800 回答
0

微软称其为“装饰”而不是修饰。它们包括一个名为“undname”的命令行工具,它将根据修饰名称生成原始名称:

C:\>undname ?ColorSelect@@YAHXZ
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?ColorSelect@@YAHXZ"
is :- "int __cdecl ColorSelect(void)"

如果你想在自己的代码中做同样的事情,你也可以这样做,使用UnDecorateSymbolName.

值得一提的是,装饰/修饰不仅支持重载,还支持类型安全链接。类型安全链接源于函数重载,尽管它本身并不是真正的函数重载。

具体来说,类型安全链接处理(例如)如何处理具有重载的 C++ 代码,例如sqrtfor floatdoublelong double,并且可能complex还有,但链接到提供 的 C 库double sqrt(double),但不提供其他重载。在这种情况下,我们通常希望在使用/使用正确的参数时使用它,而不是在其他情况下使用。

即使不涉及函数重载,这也可能(或可能)出现。例如,在纯 C 中,您可以执行以下操作:

#include <stdio.h>
extern int sqrt(int);

// ...
printf("%d", sqrt(100));

现在,我们已经告诉编译器我们正在使用一个版本,sqrt它需要(并返回)一个int. 不幸的是,链接器并没有意识到这一点,所以它仍然与sqrt标准库中的接受和返回的double. 结果,上面的代码将打印一些完全无用的结果(通常0,这并不重要)。

类型安全链接防止了这种情况——即使它不完全是函数重载,我们仍然有两个同名的函数,但在链接时类型不同。通过将参数类型编码到名称中,链接器可以像编译器一样将其分类。

当我们在不同库之间发生名称冲突时,在 C 中也会出现同样的情况(并且经常发生)。使用传统的 C 编译器,理顺这种混乱可能非常困难(充其量)。使用 C++ 编译器,除非两个库不仅使用相同的名称,而且使用相同数量和类型的参数,否则这根本不是问题。

于 2013-05-31T22:43:55.987 回答