Hen*_*nry 37 c++ name-mangling function-call
假设我有一些类似的东西
struct Foo {
void goo() {printf("Test");}
}
external void _ZN3Foo3gooEv(Foo *f);
int main() {
Foo f;
_ZN3Foo3gooEv(&f);
}
Run Code Online (Sandbox Code Playgroud)
是否可以在这里通过函数的名称修改版本调用 Foo::goo() ?
编辑:
作为澄清,这只是一个实验,看看是否可以显式调用名称损坏的函数。这里没有进一步的目标。
我认为所有成员函数基本上都将 this 指针作为它们的第一个参数。
我知道这不会链接,但我不明白为什么。我认为名称修改发生在编译时,当链接器运行时,它会解析对名称修改函数的调用。(这就是为什么我想如果我们将 _ZN3Foo3gooEv 保留为 extern,它会去符号表中查找)。
我在这里误解了什么吗?
Art*_*yer 37
你可以,但有一些警告。
您要么必须以生成代码的方式使用成员函数,要么让它不内联,并且您的extern "C"
重整定义应该是为了防止“双重重整”。例如:
#include <cstdio>
struct Foo {
const char* message;
void goo();
};
void Foo::goo() {
std::printf("%s", this->message);
}
extern "C" void _ZN3Foo3gooEv(Foo *f);
int main() {
Foo f{ "Test" };
_ZN3Foo3gooEv(&f);
}
Run Code Online (Sandbox Code Playgroud)
将正常工作并且在 gcc 中特别稳定。
这是有效的,因为成员函数的调用约定等同于大多数系统上自由函数的默认调用约定。 this
被传递给成员函数,就好像它是第一个参数一样,显式参数采用后面的 arg-passing 槽。(寄存器和/或堆栈)。我相信这对于 x86-64,至少 ARM 32 位和 64 位以及 Windows 以外的 32 位 x86 都是正确的。
铛似乎特别支持这种使用情况:它内联Foo::goo
成main
当GCC假装_ZN3Foo3gooEv
和Foo::goo
的mangling之后是两个独立的实体(并因此不能被取代和内联)。
使用 MSVC,您可以做类似的事情。但是,在 Windows 上的 x86-32 代码中,使用调用约定__thiscall
而不是将this
指针作为第一个参数传递,而是在 ECX 寄存器中与堆栈上的其他参数一起传递。如果使用 clang 或 gcc 为 x86-32 进行交叉编译,则可以使用[[gnu::thiscall]]
( __attribute__((thiscall))
)。(fastcall
如果只有一个 args 也是类似的,但是 2 个 args 会在寄存器中传递前 2 个,而不仅仅是前 1 个)。
但真的没有理由这样做。它只能被视为编译器扩展(因为它使用_Capital
符号),如果您需要一种从 C 调用这些函数的方法,请使用void Foo_goo(struct Foo*)
您在 C++ 翻译单元中定义的帮助程序。它还可以调用私有成员函数,但是您已经可以使用模板专业化以符合标准的方式执行此操作。
归档时间: |
|
查看次数: |
2049 次 |
最近记录: |