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

时间:2012-01-31 17:30:23

标签: python ctypes boost-python

我在wrapping C libraryC++ library上仔细阅读了以下两个帖子,我不确定是否已经知道了。我正在使用的C ++库确实使用了类和模板,但没有采用任何过于复杂的方式。使用ctypes包装它有什么问题或警告(除了你可以在纯python中这样做的点)?

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

由于

奥利弗

2 个答案:

答案 0 :(得分:15)

在为boost::python辩护时,给出了亚历山大在ctypes上的回答:

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

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

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

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

答案 1 :(得分:12)

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

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

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

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

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

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