为 C++ 库创建一个 c 包装器

Posted

技术标签:

【中文标题】为 C++ 库创建一个 c 包装器【英文标题】:creating a c wrapper for C++ library 【发布时间】:2016-02-25 09:43:50 【问题描述】:

通过不透明的指针将 c++ 库包装到 C 是否提供了稳定的 ABI 接口?我很清楚 ABI 接口以及为什么 c++ 没有稳定的接口。这与名称修改和许多其他事情有关。我知道C在那部分非常稳定。与 C++ 相比,将 C 库包装成各种其他语言也很容易。这两个是为我的库制作 c API 的驱动力。

将 C++ 库包装到 C 时,底层代码仍然是 C++。我的情况是带有 boost 共享 ptr 和其他依赖项的 c++。

既然底层代码是C++,那么ABI的稳定性是如何实现的。或者换句话说,共享库(.so,.dll等)中仍然编译了c++的东西。

我想知道它是如何工作的。也许有人可以为我提供一个很好地解释这些东西的例子。

【问题讨论】:

您预计会出现什么样的问题?我的意思是,你知道为什么我们认为 C++ ABI 不稳定,对吧?这些相同的原因是否适用于您的情况? .def files C/C++ DLLs的可能重复 是的,当然会有c++的东西编译到库中。但是该接口将具有稳定的 ABI,并且可以从几乎任何地方调用。确保在 API 中捕获异常并将它们转换为旧的 70 年代返回值。 "其他具体问题" 如果您的库链接到标准 C++ 库 ABI x,而其他一些库链接到标准 C++ 库 ABI y,那么这两个库可能无法一起使用(在某些平台上)至少)。您导出哪个接口并不重要。这是所有 C++ 库的问题。 “你是说代码必须用 C 重写?”您是说 C++ 不能用于编写库吗?显然存在 C++ 库,因此人们能够以某种方式应对 ABI 的不稳定性。 CppCon 2014: Stefanus DuToit "Hourglass Interfaces for C++ APIs" 你可能会感兴趣 【参考方案1】:

是的,您可以为 C++ 实现创建稳定的 C 接口。当然,C 接口只提供 C 功能。在实际实现中使用 C++ 仍然很方便。这是一个示例,其中您有一个带有函数模板的 C++ 实现,并且您为某些变体提供了 C 接口:

// Internal C++ implementation
template <typename T>
void
foo(T &a, const T &b)

    // do something



// C Interface
extern "C" 

void
sfoo(float *a, const float *b)

    foo(*a, *b);


void
dfoo(double *a, const double *b)

    foo(*a, *b);


 // extern "C"

所以基本上编译器会为T=floatT=double生成不同的实现:

当然你没有函数重载。所以你必须做名字修饰手。例如。 sfoo 用于浮点数,dfoo 用于双精度数,...(您也可以使用 C 中的预处理器来执行此操作。但阅读和维护并不是那么好。) 您没有参考资料。因此,接口公开了非常量指针,而不是引用。

【讨论】:

【参考方案2】:

是的,它将是适用于您平台的 C 编译器的稳定 C ABI;当然,如果做得好的话。

【讨论】:

以上是关于为 C++ 库创建一个 c 包装器的主要内容,如果未能解决你的问题,请参考以下文章

为 C 消费包装 C++ 类 API

OpenCv c++ 为基本打印垫功能创建一个 C 包装器?

C 库的 C++ 包装器作为共享库

将 C 库与 Haskell 库静态链接

将多个 C++ 类包装成一个 Python 类

C++ - 错误:为 OpenCV 的 cv::Scalar::all 创建 C 包装器时出现预期的类型说明符