Dumpbin显示奇怪的方法名称(在MS Visual C ++中生成导出功能)

时间:2012-12-29 19:59:06

标签: dll pinvoke dllexport dumpbin cdecl

我在VS中创建了新的Win32项目,并为此目的选择了动态库(* .dll)。

我在主文件中定义了一些导出功能:

__declspec(dllexport)
int TestCall(void)
{
    int value = 4 / 2;
    std::cout << typeid(value).name() << std::endl;
    return value;
}

__declspec(dllexport)
void SwapMe(int *first, int *second)
{
    int tmp = *first;
    *first = *second;
    *second = tmp;
}

当我看到dumpin / exports时,我得到了:

ordinal hint RVA      name

      1    0 00001010 ?SwapMe@@YAXPEAH0@Z
      2    1 00001270 ?TestCall@@YAHXZ

我正在调用C#这样的版本:

[DllImport(@"lib1.dll", EntryPoint = "?TestCall@@YAHXZ",
CallingConvention = CallingConvention.Cdecl)]
static extern int TestCall();

这不是使用导出方法的正确形式。我在C ++ DLL项目中为export-methods生成这样的名称失败了吗?

2 个答案:

答案 0 :(得分:5)

这是正常的,C ++编译器将名称修饰应用于函数。 C ++语言支持函数重载,就像C#一样。因此,您可以编写Foo(int)Foo(double)函数。显然,它们不能同时作为名为“Foo”的函数导出,客户端代码不知道要调用哪一个。因此额外的字符对名称进行编码,使其对于重载是唯一的。

您可以通过声明函数extern "C"来关闭它,C语言不支持重载,因此不需要相同类型的装饰。

但如果你不这样做,那实际上会更好。因为它也是捕捉错误的绝佳方式。就像更改C ++代码中的函数声明但忘记修改C#代码中的pinvoke声明一样。现在,您将可以轻松诊断“未找到Entrypoint”异常,而不是非描述性且非常难以诊断AccessViolationException。这不一定要在C ++代码中引发,堆栈不平衡也会导致C#代码崩溃。查找装饰名称有点痛苦,但通过要求链接器创建映射文件(/ MAP选项)来改进它。

答案 1 :(得分:2)

使用extern“C”指定链接以避免名称错位:

extern "C" __declspec(dllexport) int TestCall(void);
extern "C" __declspec(dllexport) void SwapMe(int *first, int *second);