| I think you're confusing some terms here. > In C++ you need an `extern "C"`, because C++ linkage isn't guaranteed to be the same as C linkage. `extern "C"` has nothing to do with linkage, all it does is disable namemangling, so you get the same symbol name as with a C compiler. > Throwing a C++ static function as a callback into a C function usually works, but it's not technically correct because the linkage isn't guaranteed to be the same without an extern "C". Again, linkage is not relevant here. Your C++ callbacks don't have to be declared as extern "C" either, because the symbol name doesn't matter. As you noted correctly, the calling conventions must match, but in practice this only matters on x86 Windows. (One notable example is passing callbacks to Win32 API functions, which use `stdcall` by default.) Fortunately, x86_64 and ARM did away with this madness and only have a single calling convention (per platform). |
extern "C" also ensures that the C calling convention is used, which is relevant for callbacks. It's not just name mangling. This is the reason that extern "C" static functions exist. You can actually overload a C++ function by extern "C" vs extern "C++", and it will dispatch it appropriately based on whether the passed in function is declared with C or C++ linkage.
And I'm not sure the terms are confused, because that's how most documentation refers to it: https://learn.microsoft.com/en-us/cpp/cpp/extern-cpp?view=ms...
> In C++, when used with a string, extern specifies that the linkage conventions of another language are being used for the declarator(s). C functions and data can be accessed only if they're previously declared as having C linkage. However, they must be defined in a separately compiled translation unit.
And https://en.cppreference.com/w/cpp/language/language_linkage
The post you're replying to had it completely right. extern "C" is entirely about linkage, which includes calling convention and name mangling.
> As you noted correctly, the calling conventions must match, but in practice this only matters on x86 Windows.
Or if you want your program to actually be correct, instead of just incidentally working for most common cases, including on future systems.
If you're passing a callback to a C function from C++, it's wrong unless the callback is declared extern "C".