This is due to a name change being made by C ++.
extern "C" vs no extern "C"
As an example, here is shown what CFF Explorer shows for the dll export table. The first was built with the borland C ++ compiler. The second was built using msvc.
Ordinal FunctionRVA Name RVA Name 00000001 0020E140 0032C2B6 createDevice 00000002 0020E244 0032C2C3 createDeviceEx 0000000D 00328DA4 0032C0C1 @irr@core@IdentityMatrix 0000000E 00328DE4 0032C28A @irr@video@IdentityMaterial
0000000C 000F9C80 001EE1B6 createDevice 0000000D 000F9CE0 001EE1C3 createDeviceEx 00000001 00207458 001EDDC7 ?IdentityMaterial@video@irr@@3VSMaterial@12@A 00000002 001F55A0 001EDDF5 ?IdentityMatrix@core@irr@@3V?$CMatrix4@M@12@B
The first 2 functions createDevice and createDeviceEx contain the extern "C" signature in their prototype, while the others do not. Note the coding difference when using C ++ mangling. The difference really goes deeper than that.
ABI and standardization
As explained in other answers, the C ++ standard does not specify I unstructured A bstract B. This means that vendors who develop their tools can pretty much do everything they need when it comes to how function calls are handled and how overloading works under the hood - while it demonstrates the expected behavior dictated by the standard.
With all of these different coding schemes, there is no other way that another language may have the hope of working with modules compiled with C ++. Heck modules compiled with one C ++ compiler are unlikely to work with another! Compiler providers are free to change their encoding between versions at their discretion.
In addition, no common ABI means that there is no common expected way to call these functions / methods. For example, one compiler can pass its arguments to the stack, and another compiler can pass it to the register. One could pass arguments from left to right, and the other could be undone. If only one of these aspects does not exactly match between the caller and the callee, then your application will crash ... that is, if you're lucky. Instead of dealing with this, vendors simply say no, causing a build error with different encodings.
OTOH, while C does not have a standardized ABI, C is a much simpler language to compare. Most C compiler providers handle the decoration function and call mechanism in a similar way. As a result, there is a kind of βde factoβ standard, even if the ABI is not explicitly specified in the standard. With this community, it simplifies the interaction of other languages ββwith modules compiled with C.
For example, the decoration __stdcall in a function signature is understood as a specific calling convention. The arguments are pushed from right to left, and the caller is responsible for clearing the stack afterwards. __cdecl similar, but it understands that the caller is responsible for clearing the stack.
Bottom line
If the module in question should interact with languages ββoutside of C ++, it should be properly decorated and exposed as an API C, this is the best choice. Note that you are giving up some flexibility by doing this. In particular, you will not be able to overload these functions, since the compiler can no longer generate unique characters for each overload using mangling.
If interoperability is not important for the module in question - it will be used only with the same tool with which it was built, and then omit the extern "C" decor from your prototypes.