【问题标题】:Dumpbin shows strange method name (generating exporting function in MS Visual C++)Dumpbin 显示奇怪的方法名称(在 MS Visual C++ 中生成导出函数)
【发布时间】:2012-12-29 19:59:05
【问题描述】:

我在我的 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;
}

当我查看转储 /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 项目中的导出方法生成此类名称失败了?

【问题讨论】:

    标签: dll pinvoke dllexport dumpbin cdecl


    【解决方案1】:

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

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

    但实际上,如果你不这样做会更好。因为它也是捕捉错误的好方法。就像更改 C++ 代码中的函数声明但忘记修改 C# 代码中的 pinvoke 声明一样。您现在将获得一个易于诊断的“找不到入口点”异常,而不是一个非描述性且非常难以诊断的 AccessViolationException。不一定必须在 C++ 代码中提出,堆栈不平衡也可能使您的 C# 代码崩溃。查找修饰名称有点痛苦,但是通过要求链接器创建映射文件(/MAP 选项)来改进它。

    【讨论】:

      【解决方案2】:

      使用 extern "C" 指定链接以避免名称混乱:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-10
        • 2011-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多