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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…