Consider the following code:
#include <iostream>
struct Foo {
void work() { std::cout << "foo" << std::endl; }
};
typedef void function_type(void *arg);
template <typename T>
void function(void *arg)
{
auto &t = *reinterpret_cast<T*>(arg);
t.work();
}
void call_function(function_type *fn, void *arg)
{
fn(arg);
}
int main()
{
Foo foo;
call_function(&function<Foo>, &foo);
return 0;
}
If call_function() would be an interface of some C library (which is linked dynamically to my program), is it OK to pass a pointer to some specific instance of a template function? Are there any differences between pointers to (a instantiation of) a template function and regular functions?
In the code as shown, both the functions have C++ language linkage, and everything is fine. You're not passing a template function, you're passing a regular function instantiated from a function template.
Once any template is instantiated, it's not really a template any more, much like instantiating a class gives you an object, and not another class.
There is something missing though - for linking a C program, you need to import the interface as extern "C"
and use that linkage for any function pointers you pass to it. Otherwise the C and C++ sides may disagree on the calling convention to use, and everything will go horribly wrong.
Since the standard explicitly says
A template, a template explicit specialization, and a class template partial specialization shall not have C linkage
we need some workaround. As usual, your C callback takes an argument, so there's nothing stopping you from switching calling conventions in a C-linkage trampoline function:
extern "C" {
void bounce(void *arg)
{
static_cast<Trampoline *>(arg)->callback();
}
}
where callback
will be a normal C++-linkage function, including a function template instantiation (or just a std::function
or whatever).
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