是否允许将模板函数的指针传给C库?(作为回调)[重复]。

问题描述 投票:6回答:1

考虑下面的代码。

#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;
}

如果call_function()是某个C库的接口(动态链接到我的程序),那么是否可以传递一个指向模板函数特定实例的指针?指向(模板函数的实例)的指针和常规函数之间有什么区别吗?

c++ c templates metaprogramming
1个回答
12
投票

在如图所示的代码中,两个函数都有C++语言的链接,一切正常。你传递的不是模板函数,而是普通函数。从函数模板实例化.

一旦任何模板被实例化,它就不是真正的模板了,就像实例化一个类给你一个 对象而不是其他类。

但还缺少一些东西--如果要链接一个C程序,你需要将接口导入到一个C程序中,作为 extern "C" 对于你传递给它的任何函数指针,都要使用该链接。否则,C和C++双方可能会在使用的调用约定上产生分歧,一切都会出现可怕的错误。

由于标准中明确规定

模板、模板显式特化和类模板局部特化不得有C链接

我们需要一些变通的方法。像往常一样,你的C语言回调需要一个参数,所以没有什么能阻止你在C语言连接的蹦床函数中切换调用约定。

extern "C" {
    void bounce(void *arg)
    {
        static_cast<Trampoline *>(arg)->callback();
    }
}

其中 callback 将是一个普通的C++链接函数,包括一个函数模板实例化(或者只是一个 std::function 或什么的)。)

© www.soinside.com 2019 - 2024. All rights reserved.