如何使用语言包装器构建C ++库?

时间:2018-05-27 03:44:51

标签: c++ build shared-libraries

我对编写包含其他语言包装器的C ++库的良好实践有疑问,例如Python和Matlab。这可能是一个简单的问题或重复,但我没有找到一个好的资源或其他答案,这有助于解释如何做到这一点。

对于后台,我正在开发一个C ++库项目,其中包含专门用于与其他语言兼容的C包装器。该库是一个用C ++编写的科学计算库,我已经为函数和类编写了C包装器,用作共享库的一部分。

我的问题是如何将C包装器合并到其他语言的模块中,例如Python和Matlab的包装器库。我没有要求具体说明如何为这些其他语言实现代码,因为这完全是另一个问题,我已经基本了解了如何编写可以为每种语言构建和加载的代码它自己的图书馆。我的问题主要是将C包装器包含在其他构建中。

例如,我有以下目录结构,其中每个文件夹包含与不同语言/模块相关的代码。

top
├─ matlab
│  ├─ CMakeLists.txt
│  ├─ matlab_wrapper.hpp
│  └─ matlab_wrapper.cc
├─ python
│  ├─ CMakeLists.txt
│  ├─ python_wrapper.hpp
│  └─ python_wrapper.cc
├─ src
│  ├─ CMakeLists.txt
│  ├─ c_wrapper.hpp
│  ├─ c_wrapper.cc
│  └─ other code...
└─ CMakeLists.txt

我知道每个文件夹应该是自给自足的,并且可以自行构建,但是我无法弄清楚如何分发代码以便它包含C包装器。基本上,我在c_wrapper文件中有C实现,我想在matlab和python库中使用它。

通常情况下,我会在构建步骤中包含其他源文件并完成它(这可能就是答案),但src文件夹中的所有内容都是作为自己的共享库构建和分发的。在matlab_wrapperpython_wrapper文件中重写C包装器(基本上创建同一函数的3个版本)或在另一个的构建步骤中包含c_wrapper文件似乎是多余的库因为它们已经包含在主C ++库中。

我不是打包共享库的专家,那么最好的方法是什么?我是否应该在构建步骤中包含c_wrapper源文件,在每个模块中重写C ++包装器,还是有另一种方法将包含在c_wrapper中的代码包含在包装器库中?理想情况下,每个模块将共享相同(或非常相似)的API,因此如果有一种方法可以包含此代码而不必在每次添加新的C包装器时重写相同的函数,那将会很棒。非常感谢任何帮助或建议。

1 个答案:

答案 0 :(得分:1)

您可以为所有目的创建一个共享库:毕竟,只有Matlab会忽略Python looks forPyInit_foo。但是你仍然可能不想改变你的主库以支持这样的用途:也许它有其他编译客户端不需要包装器,或者它可能与特殊包装器分开安装,或者它可能需要在没有包装器的情况下可用安装的主机。

另一个选择是为每个终极客户端创建一个共享库。将相同的目标文件链接到每个目标文件都会破坏共享库的一些用途,例如在Matlab进程和每个使用您的库的并发Python进程之间共享内存。它可能(我不确定)也不止一次地运行全局构造函数,但无论如何最好避免这些。这些问题可能对您的用例无关紧要,但适用于真实C ++库的构建问题与之前相同。

否则,您将在一个进程中拥有多个共享库(一个用于“真正的”C ++库,另一个用于宿主语言模块)。这里有ABI issues;避免它们的一种方法是,如您所建议的那样,在核心库中提供C API。当然,还有其他方法可以解决这些问题,特别是在你控制所有编辑时。

还有更多的方法:主库可以包含一种主机语言的接口(特别是如果它也可以作为C API)而不是另一种,或者一个共享库可以提供多种语言而不包括C ++核心。给定C API,您可以使用来自主机语言(ctypes用于Python),而不是专门为主机编写(更多)C。 / p>

无论您选择哪种链接策略,编译始终是相同的:只需#include您的任何标题相关(适用于C API的标题)以及主机语言所需的任何标题(如果有的话)然后去。