If I have a function in a .c like
如果我在.c中有一个函数
void foo(int c, char v);
...in my .obj, this becomes a symbol named
......在我的.obj中,这就成了一个名字
_foo
...as per C name mangling rules. If I have a similar function in a .cpp file, this becomes something else entirely, as per the compiler-specific name mangling rules. msvc 12 will give us this:
......根据C名称修改规则。如果我在.cpp文件中有类似的功能,那么根据特定于编译器的名称修改规则,这将成为完全不同的东西。 msvc 12会给我们这个:
?foo@@YAXHD@Z
If I have that function foo in the .cpp file and I want it to use C name mangling rules (assuming I can do without overloading), we can declare it as
如果我在.cpp文件中有这个函数foo并且我希望它使用C名称修改规则(假设我可以不重载),我们可以将其声明为
extern "C" void foo(int c, char v);
...in which case, we're back to good old
......在这种情况下,我们又恢复了良好的状态
_foo
...in the .obj symbol table.
...在.obj符号表中。
My question is, is it possible to go the other way around? If I wanted to simulate C++ name mangling with a C function, this would be easy with gcc because gcc's name mangling rules only make use of identifier-friendly characters, thus the mangled name of foo becomes _ZN3fooEic, and we could easily write
我的问题是,是否有可能走另一条路?如果我想用C函数模拟C ++名称修改,那么使用gcc会很容易,因为gcc的名称修改规则只使用了标识符友好的字符,因此foo的错误名称变成了_ZN3fooEic,我们可以轻松编写
void ZN3fooEic(int c, char v);
Back in Microsoft-compiler-land, I obviously can't create a function whose name is a completely invalid identifier called
回到Microsoft-compiler-land,我显然无法创建一个名为完全无效的标识符的函数
void ?foo@@YAXHD@Z(int c, char v);
...but I'd still like that function to show up with that symbol name in the .obj symbol table.
...但我仍然希望该函数在.obj符号表中显示该符号名称。
Any ideas? I've looked through Visual C++'s supported pragmas, and I don't see anything useful.
有任何想法吗?我查看了Visual C ++支持的pragma,但我没有看到任何有用的东西。
3 个解决方案
#1
6
You can do this using __identifier
:
您可以使用__identifier执行此操作:
#include <stdio.h>
#pragma warning(suppress: 4483)
extern "C" void __cdecl __identifier("?foo@@YAXHD@Z")(int c, char v)
{
printf("%d %c\n", c, v);
}
void __cdecl foo(int, char);
int main()
{
foo(10, 'x');
}
#2
7
You're right. That's not (directly) possible (note: never trust VSC++). However, there exists a nifty workaround if you really need this. First of all, in the C++ file...
你是对的。这不是(直接)可能的(注意:永远不要相信VSC ++)。但是,如果你确实需要这个,那么有一个很好的解决方法。首先,在C ++文件中......
extern "C" int proxy(int i, char c);
int foo(int i, char c)
{
return proxy(i, c);
}
Then, in the C file...
然后,在C文件中......
int proxy(int i, char c)
{
// Do whatever you wanna do here
}
Without having to type any mangled name at all, you are now able to call the foo
function, which is actually just a wrapper around the C function proxy
. This gives you the same effect as if proxy
was actually foo
, from C++'s point of view. The single penalty here is of course a quick 'n' dirty function call. If the ABI allows it, and the compiler is smart enough, this can be replaced with a single JMP
x86 instruction.
您根本无需键入任何受损名称,现在可以调用foo函数,它实际上只是C函数代理的包装器。从C ++的角度来看,这给你的效果就像代理实际上是foo一样。这里的单一惩罚当然是快速'n'脏函数调用。如果ABI允许它,并且编译器足够智能,则可以用单个JMP x86指令替换它。
Another way would be to write a function foo
in C, and then use MinGW's objcopy
in order to rename the symbol...
另一种方法是在C中编写一个函数foo,然后使用MinGW的objcopy来重命名符号......
$ objcopy --redefine-sym "foo=?foo@@YAXHD@Z" foobar.obj
I'm not sure if that's possible just with VSC++ tools. It would be very unstable, unportable, and hacky anyways.
我不确定是否可以使用VSC ++工具。无论如何,这将是非常不稳定,不可移植和hacky。
#3
6
You might get it to work using a .DEF file. Define your function in your foo.cpp
:
您可以使用.DEF文件使其工作。在foo.cpp中定义你的函数:
void foo(int c, char v) { ... }
Then pass a def file to the linker, that looks like this:
然后将def文件传递给链接器,如下所示:
LIBRARY mylib
EXPORTS
?foo@@YAXHD@Z=_foo
Disclaimer: untested, I might be missing some details.
免责声明:未经测试,我可能会遗漏一些细节。
#1
6
You can do this using __identifier
:
您可以使用__identifier执行此操作:
#include <stdio.h>
#pragma warning(suppress: 4483)
extern "C" void __cdecl __identifier("?foo@@YAXHD@Z")(int c, char v)
{
printf("%d %c\n", c, v);
}
void __cdecl foo(int, char);
int main()
{
foo(10, 'x');
}
#2
7
You're right. That's not (directly) possible (note: never trust VSC++). However, there exists a nifty workaround if you really need this. First of all, in the C++ file...
你是对的。这不是(直接)可能的(注意:永远不要相信VSC ++)。但是,如果你确实需要这个,那么有一个很好的解决方法。首先,在C ++文件中......
extern "C" int proxy(int i, char c);
int foo(int i, char c)
{
return proxy(i, c);
}
Then, in the C file...
然后,在C文件中......
int proxy(int i, char c)
{
// Do whatever you wanna do here
}
Without having to type any mangled name at all, you are now able to call the foo
function, which is actually just a wrapper around the C function proxy
. This gives you the same effect as if proxy
was actually foo
, from C++'s point of view. The single penalty here is of course a quick 'n' dirty function call. If the ABI allows it, and the compiler is smart enough, this can be replaced with a single JMP
x86 instruction.
您根本无需键入任何受损名称,现在可以调用foo函数,它实际上只是C函数代理的包装器。从C ++的角度来看,这给你的效果就像代理实际上是foo一样。这里的单一惩罚当然是快速'n'脏函数调用。如果ABI允许它,并且编译器足够智能,则可以用单个JMP x86指令替换它。
Another way would be to write a function foo
in C, and then use MinGW's objcopy
in order to rename the symbol...
另一种方法是在C中编写一个函数foo,然后使用MinGW的objcopy来重命名符号......
$ objcopy --redefine-sym "foo=?foo@@YAXHD@Z" foobar.obj
I'm not sure if that's possible just with VSC++ tools. It would be very unstable, unportable, and hacky anyways.
我不确定是否可以使用VSC ++工具。无论如何,这将是非常不稳定,不可移植和hacky。
#3
6
You might get it to work using a .DEF file. Define your function in your foo.cpp
:
您可以使用.DEF文件使其工作。在foo.cpp中定义你的函数:
void foo(int c, char v) { ... }
Then pass a def file to the linker, that looks like this:
然后将def文件传递给链接器,如下所示:
LIBRARY mylib
EXPORTS
?foo@@YAXHD@Z=_foo
Disclaimer: untested, I might be missing some details.
免责声明:未经测试,我可能会遗漏一些细节。