将模板实例化导出为C函数

时间:2014-04-16 14:29:41

标签: c++ c templates c++11 shared-libraries

我正在为C库创建Haskell绑定。但是,我想让库的调用约定更适合Haskell,所以我创建了一个模板类,它有一个静态方法,当你按照以下方式使用它时会调用正确的方法:

Wrap<decltype(&libraryFunction), &libraryFunction>::call(...);

...表示参数。这很好,编译器显然为我生成了包装器代码。我甚至可以使用&运算符来获取此函数的地址,因此它显然只是一个常规函数。

但是,Haskell不能使用C ++模板,所以我想要做的是显式实例化所需函数的模板,并将它们导出为常规C函数,我可以从Haskell中引用它。我知道我可以创建手动调用这个静态成员函数的存根,但是让我说我​​真的不喜欢它。

关于如何做到这一点的任何想法?便携式或非便携式,我想知道是否可能。

1 个答案:

答案 0 :(得分:2)

这不可能移植:

  

<强> [温度] / 4

     

模板,模板显式特化和类模板部分特化不应具有C链接。

请注意,这也会阻止您使用指向该函数的指针,让Haskell通过此指针调用该函数:不保证例如C ++函数的调用约定(在C ++程序中)与Haskell对其获得的函数指针所假设的相同。

可移植的是导出单个extern "C"函数,该函数在C和C ++语言链接之间进行转换。您可以将函数指针或其他类型的标识符传递给Haskell,Haskell调用此单个C函数传递它实际要调用的函数的标识符:

std::map<int, void(*)(int32_t)> functions;

extern "C" interface_fct(int id, int32_t arg)
{
    functions[id](arg);
}

对于具有不同参数集的函数,这当然不是很有用。

您可以编写类似于va_args(但更安全)的内容来传递任意参数,但写一些不可移植的东西可能更有用。