如果我在.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 ++支持的编译指示,但我没有看到任何有用的内容。
答案 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
免责声明:未经测试,我可能会遗漏一些细节。