用ctypes包装C++库是个坏主意吗?

Oli*_*ver 11 python ctypes boost-python

我在包装C库C++库时阅读了以下两个主题,我不确定是否已经得到它.我正在使用的C++库确实使用了类和模板,但没有采用任何过于复杂的方式.用ctypes包装它有什么问题或警告(除了你可以在纯python等中这样做)?

PyCXX,Cython和boost :: python是人们提到的另外三个选择,有没有一个更适合C++的共识?

谢谢

奥利弗

Jam*_*mes 15

为了辩护boost::python,鉴于亚历山大对ctypes的回答:

Boost python 在c ++和python代码之间提供了一个非常 "c ++"的接口 - 即使像c ++类的允许python子类那样覆盖虚拟方法也是相对简单的.这是一个很好的功能的盆栽列表:

  • 允许python子类重写C++类的虚方法.
  • 桥接std::vector<>,std::map<>实例和python列表和词典(使用vector_indexing_suitemap_indexing_suite)
  • boost::shared_ptr使用python引用计数自动共享智能指针(等)中的引用计数(您可以将其扩展到任何智能指针).
  • 传递参数和从函数返回值时,对所有权进行细粒度控制.

基本上,如果你有一个想要以忠实于语言的方式公开c ++接口的设计,那么boost :: python可能是最好的方法.

唯一的缺点是增加了编译时间(boost :: python广泛使用模板),如果你没有把事情做得很好,有时会出现不透明的错误信息.

  • 另一个问题是boost和python版本的强大耦合.例如,如果升级python版本,则必须重建boost版本 (4认同)

Ale*_*ler 12

对于C++,可以从Python访问的库必须使用C导出名称,这基本上意味着foo可以从ctypes访问名为的函数foo.

只能通过封装公共接口来实现,而公共接口export C {}又不允许函数重载和模板(只有要包装的库的公共接口是相关的,内部工作不是并且可以使用他们喜欢的任何C++特性).

原因是C++编译器使用名为mangling的机制为重载或模板化符号生成唯一名称.虽然ctypes如果你知道它的错误名称仍会找到一个函数,但是修改方案取决于所使用的编译器/链接器,并且你无法依赖它.简而言之:不要使用ctypes来封装在其公共接口中使用C++功能的库.

Cython采取不同的方法.它可以帮助您构建一个C扩展模块,该模块与原始库进行交互.因此,通过常规C++链接机制来链接到C++库,从而避免了上述问题.Cython的问题在于需要为每个平台重新编译C扩展库,但无论如何,这也适用于要包装的C++库.

就个人而言,我会说在大多数情况下,启动Cython的时间是一个花费很多的时间,并且最终会与ctypes相比得到回报(除了非常简单的Cish接口).

我没有任何经验boost.python,所以我不能对它发表评论(但是,我不会觉得它很受欢迎).