Suppose I have something along the lines of
struct Foo { void goo() {printf("Test");} } external void _ZN3Foo3gooEv(Foo *f); int main() { Foo f; _ZN3Foo3gooEv(&f); }
Is it possible to call Foo::goo() through the name mangled version of the function here?
Edit:
As a clarification, this is just an experiment to see if it's possible to explicitly call a name mangled function. There is no further goal here.
I was thought that all member functions basically take the this pointer as their first argument.
I get that this won't link, but I don't get why. I thought that name mangling happens at compile time, and when the linker runs it resolves the calls to the name mangled function. (That's why I figured if we leave _ZN3Foo3gooEv as extern, it would go to the symbol table to look it up).
Am I misunderstanding something here?
Name mangling is the encoding of function and variable names into unique names so that linkers can separate common names in the language. Type names may also be mangled. Name mangling is commonly used to facilitate the overloading feature and visibility within different scopes.
The need for name mangling arises where the language allows different entities to be named with the same identifier as long as they occupy a different namespace (typically defined by a module, class, or explicit namespace directive) or have different signatures (such as in function overloading).
You can, with some caveats.
You either have to use the member function in a way that code will be generated or have it be not inline, and your mangled definition should be extern "C"
to prevent "double mangling". E.g.:
#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); }
will work fine and be stable specifically in gcc.
This works because the calling convention for member functions is equivalent to the default calling convention for free functions on most systems. this
is passed to member functions as if it was the first argument, with explicit arguments taking the later arg-passing slots. (Registers and/or stack). I believe that this is true for x86-64, ARM 32-bit and 64-bit at least, and 32-bit x86 other than Windows.
clang seems to specifically support this use case: It inlines Foo::goo
into main
when gcc pretends that _ZN3Foo3gooEv
and Foo::goo
after mangling are two separate entities (and thus can't be substituted and inlined).
With MSVC, you can do something similar. However, in x86-32 code on windows, the calling convention __thiscall
is used where instead of passing the this
pointer as the first argument, it is passed in the ECX register with other args on the stack. If cross compiling for x86-32 with clang or gcc, you can use [[gnu::thiscall]]
(__attribute__((thiscall))
). (fastcall
is similar if there's only one arg, but with 2 args would pass the first 2 in registers, not just the first 1).
But there really should be no reason to do this. It can only be viewed as a compiler extension (Since it uses _Capital
symbols), and if you need a way to call these functions from C, use a helper void Foo_goo(struct Foo*)
that you define in a C++ translation unit. It can also call private member functions, but you can already do this in a standards-compliant way with template specialisations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With