I want to pass the pointer of an instance of a template function to a C function as callback. And It's obviously impossible to declare the template in extern "C"
.
Is it guaranteed that C++ uses the same calling convention with C for nonmember function? And is there any other effect of declaring a function in extern "C"
besides it prevents incompatible name mangling?
Its a bad idea to export C++ methods or template functions directly for a C library. If I have a C++ program then I usually put the C bindings into its separate .cpp + .h file pair and I surround the header file with and extern "C"
block and I use only C compatible function declarations there. In the accompanying .cpp file you implement the functions and since its a .cpp file you can access C++ features (templates, classes, ...) in the actual implementation of the binding functions even if their signature is C compatible using C-friendly types.
In your case this case you should put a C binding function into this binder .cpp+.h file and from the implementation of that function you would be able to call an instance of the specified template function easily.
Simple stupid example:
CBindings.h:
// This is the header used by both C++ and C
#ifdef __cplusplus
extern "C" {
#endif
// C compatible function declarations with C-friendly types.
int int_from_string(const char* s);
#ifdef __cplusplus
}
#endif
CBindings.cpp:
#include "CBindings.h"
#include "WhateverCPPHeader.h"
int int_from_string(const char* s)
{
// Since the implementation is in a .cpp file here we can do C++ish things.
return FromString<int>(s);
}
WhateverCPPHeader.h:
// Somewhere in your C++ header files:
template <typename T>
T FromString(const std::string& s);
...
// Template specializations of FromString for several T types
...
Whatever.c:
#include "CBindings.h"
#include <stdio.h>
void my_c_func(void)
{
int i = int_from_string("5");
printf("%d\n", i);
}
This works on all platforms without problems and the cut between C/C++ is clearly separated into its own file.
No. It's not guaranteed that it uses the same calling convention. You can use the calling convention modifiers like _stdcall
, cdecl
, pascal
, etc. So you have to make sure that both sides know the same calling convention.
One way would be detecting the mangled name and define a proper prototype for the C function.
Consider changing the design; since you can't benefit from the template in C anyway, you can define a simple C++ function (defined extern "C") that calls the templated function.
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