Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it allowed to pass a pointer to a template function to C library? (as a callback) [duplicate]

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?

like image 918
Igor Avatar asked Apr 29 '20 12:04

Igor


Video Answer


1 Answers

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).

like image 175
Useless Avatar answered Sep 22 '22 21:09

Useless