2016-03-07 31 views
8

如果我有一个像有谁知道如何在Visual C++中手动调整名称?

void foo(int c, char v); 

...在我的obj的.C功能,这成为了一个名为

_foo 

符号......为的每个C名字改编规则。如果我在.cpp文件中具有类似的功能,则根据特定于编译器的名称修改规则,这完全变成了其他内容。 MSVC 12会给我们这样的:

[email protected]@[email protected] 

如果我在.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); 

早在微软编译土地,我显然不能创建一个名称是叫

void [email protected]@[email protected](int c, char v); 

完全无效的标识符的功能......但我还是喜欢那个函数来显示.obj符号表中的那个符号名称。

任何想法?我查看了Visual C++支持的编译指示,我没有看到任何有用的东西。

+3

@mustafagonul我不是要还原函数 - 我试图裂伤。 –

+2

即使你可以这样做,你也必须以某种方式匹配ABI。你在这个树上吠叫错了树。使用extern“C”来接受这个限制。 – xaxxon

+2

@mustafagonul你不完全理解这一点。我知道这个破烂不堪的名字是什么。我想在C文件中伪造C++名称。 –

回答

5

可以使用__identifier做到这一点:

#include <stdio.h> 

#pragma warning(suppress: 4483) 
extern "C" void __cdecl __identifier("[email protected]@[email protected]")(int c, char v) 
{ 
    printf("%d %c\n", c, v); 
} 

void __cdecl foo(int, char); 

int main() 
{ 
    foo(10, 'x'); 
} 
+0

你有什么理由相信这实际上有效吗? 我刚试过,它只接受C++关键字,而不是任意字符串。 –

+1

@TurkeyMan它的工作原理。 '#pragma warning(suppress:4483)'是必需的。如果你省略了,你会得到'warning C4483:syntax error:expected C++ keyword',这是默认的错误。 –

+0

@JamesMcNellis这正是我正在寻找的。就像凯米兰德的做法那样具有创造性,我想我会将接受的答案转换为这个答案(当然,这些优秀答案都是投票)。 –

7

你说得对。这不是(直接)可能的(注意:永远不要相信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 "[email protected]@[email protected]" foobar.obj 

我不知道如果可能的话只是VSC++工具。无论如何,这将是非常不稳定的,不可移植的,而且很无聊。

+1

由于与函数序言有关的许多原因,它并不完全是我想要的,但它可能是唯一的解决方案。 –

+1

@TedMiddleton:查看修改。实际上有另一种解决方案。 – 3442

+1

在mingw中使用objcopy实际上听起来像是一个很好的解决方案。谢谢! –

6

您可能会使用.DEF文件使其工作。 定义你的函数在foo.cpp

void foo(int c, char v) { ... } 

然后通过一个def file到链接器,看起来像这样:

LIBRARY mylib 
EXPORTS 
    [email protected]@[email protected]=_foo 

免责声明:未经检验的,我可能会丢失一些细节。

+0

我目前只能访问MSVC2008,并且此解决方案*不起作用*。基本上,链接器将def文件中的“@”解释为特殊字符,因此导出的符号仅为“?foo”。也许这在编译器的更新版本中已经发生了变化。 – sbabbi

+0

我其实也在MSVC2013上试过这个,并且它不起作用 - 正如你所说的那样,它会在第一个'@'字符处截断。你会认为这是因为链接器将@字符与序号字段混淆,但它不是 - 当我有一个像“?foo @@ YAXHD @ Z = _foo @ 24”的符号时,就像你我?富,但它仍然得到正确的序数,24. –

相关问题