I’m using a C library (from C++) which provides the following interface:
void register_callback(void* f, void* data);
void invoke_callback(
This should work:
template <typename T>
void do_register_callback(T& value) {
void (*callback)(void*) = my_callback<T>;
register_callback(reinterpret_cast<void*>(callback), &value);
}
The first line forces the compiler to instantiate that function to generate the address - which you can then happily pass.
EDIT: Let me throw another option in to this mix. Make my_callback a static member of a class template - something like the following:
template <typename T>
struct foo
{
static void my_callback(void* data) {
T& x = *static_cast<T*>(data);
std:: cout << "Call[T] with " << x << std::endl;
}
};
Now, in your register guy, you don't even need the "cast".
template <typename T>
void do_register_callback(T& value) {
register_callback(reinterpret_cast<void*>(&foo<int>::my_callback), &value);
}
It appears that the rule for instantiating class templates is different to function templates - i.e. to take the address of a member of a class, the type is instantiated.
Apparently, the real problem was the missing static_cast in my original code:
register_callback(reinterpret_cast<void*>(&my_callback<int>), &ft);
This compiles fine, but triggers the liker error when using GCC 4.5. It doesn’t even compile when using GCC 4.2, instead giving the following compile error:
insufficient contextual information to determine type
Once this “contextual information” is provided, the code compiles and links:
register_callback(reinterpret_cast<void*>(
static_cast<void(*)(void*)>(my_callback<int>)), &value);
I’ve got no idea whether the cast is actually required and (if so) why GCC 4.5 allows me to leave it off, and then fails to instantiate the template. But at least I got the code to compile without resorting to hacks.
POSIX recommends the following way to cast between function pointer types and object pointer types (which is undefined in C99):
typedef void function_type(void*);
function_type *p_to_function = &my_callback<T>;
void* p_to_data = *(void**)&p_to_function;
// Undefined:
// void* p_to_data = (void*)p_to_function;
Notice that in C++-land, this would perform a reinterpret_cast<void**>(&p_to_function) from function_type**. This is not undefined but instead implementation-defined, unlike reinterpret_cast<void*>(p_to_function). So it's probably your best bet to write C++-conformant code that relies on the implementation.