如何在Visual C ++中手动破坏名称?

时间:2016-03-07 06:43:24

标签: c++ c visual-c++ gcc linker

如果我在.c中有一个函数

void foo(int c, char v);

...在我的.obj中,这变成了一个名为

的符号
_foo

...根据C名称修改规则。如果我在.cpp文件中有类似的功能,那么根据特定于编译器的名称修改规则,这将成为完全不同的东西。 msvc 12会给我们这个:

?foo@@YAXHD@Z

如果我在.cpp文件中有这个函数foo并且我希望它使用C名称修改规则(假设我可以没有重载),我们可以将其声明为

extern "C" void foo(int c, char v);

......在这种情况下,我们又回到了旧的

_foo

...在.obj符号表中。

我的问题是,是否有可能走另一条路?如果我想用C函数模拟C ++名称修改,那么使用gcc会很容易,因为gcc的名称修改规则只使用了标识符友好的字符,因此foo的错误名称变成_ZN3fooEic,我们可以轻松编写

void ZN3fooEic(int c, char v);

回到Microsoft-compiler-land,我显然无法创建一个名为

的完全无效的标识符的函数
void ?foo@@YAXHD@Z(int c, char v);

...但我仍然希望该功能在.obj符号表中显示该符号名称。

有什么想法吗?我查看了Visual C ++支持的编译指示,但我没有看到任何有用的内容。

2 个答案:

答案 0 :(得分:8)

你是对的。这不是(直接)可能的(注意:永远不要相信VSC ++)。但是,如果您真的需要这个,那么存在一个非常好的解决方法。首先,在C ++文件中......

extern "C" int proxy(int i, char c);

int foo(int i, char c)
{
    return proxy(i, c);
}

然后,在C文件中......

int proxy(int i, char c)
{
    // Do whatever you wanna do here
}

无需输入任何受损的名称,您现在可以调用foo函数,它实际上只是C函​​数proxy的包装器。从C ++的角度来看,这为您提供了与proxy实际上foo相同的效果。这里的单一惩罚当然是一个快速的' n'脏函数调用。如果ABI允许它,并且编译器足够智能,则可以用单个JMP x86指令替换它。

另一种方法是在C中编写一个函数foo,然后使用MinGW' objcopy重命名该符号......

$ objcopy --redefine-sym "foo=?foo@@YAXHD@Z" foobar.obj

我不确定是否可以使用VSC ++工具。无论如何,它会非常不稳定,不可移植和黑客。

答案 1 :(得分:6)

您可以使用.DEF文件使其工作。 在foo.cpp

中定义您的功能
void foo(int c, char v) { ... } 

然后将def file传递给链接器,如下所示:

LIBRARY mylib
EXPORTS
   ?foo@@YAXHD@Z=_foo

免责声明:未经测试,我可能会遗漏一些细节。