为 Python 导出 C++ 类

Export of C++ classes for Python

我有一个用 C++ 编写的程序(目前作为静态库)具有非常抽象的接口,在我的 类 等上使用运算符重载。我想从中创建一个共享库(DLL on Windows 将是第一步,在尝试其他平台之前)在其他 "user friendly" 语言中使用它。我读到 Python 的 ctypes 对此有一定程度的支持。

我只是想知道,如果可以在 Python 中使用来自 C++ DLL 的一些更高级别的抽象来选择正确的选项,然后再投入时间尝试做某事,那是不可能的。用户应该能够初始化我的程序提供的 类 并将它们与他们的所有方法一起使用,包括重载运算符(当然只有 python 中可用的那些)。或者 Python 只是为了支持一些简单的函数调用等?

C++ 代码(即使只是用户可访问的 类)非常庞大,我想避免创建单独的 Python 包装器,因为所有需要的功能都已在 C++ 中完成。

由于没有人回答,我将同时提供我自己收集的所有内容。希望对某些人有所帮助。

Python 的 ctypes 旨在仅支持 C 语言功能。因此无法使用 ctypes 从 Python 直接访问 类 和其他 C++ object。但是,有一些方法可以访问它们。

繁琐的方法

为 C++ 类 创建 C 样式 object,然后为它们创建 Python 包装器。

C 风格 object 基本上是指向动态分配的 C++ object 的指针。它应该有额外的方法,例如通常命名为 ->Release() 的方法来销毁 object 并释放分配的内存。然后,您需要手动创建 python 包装器,类似于原始 C++ object,包括重载运算符等。(旁注:我遇到的唯一运算符,在这种情况下可能需要,但不是Python 中可重载的是赋值运算符。)

当您想完全控制正在发生的事情并且不介意在 Python 中复制界面时,这可能是最好的解决方案。

快速方法

Boost 提供了一个 Boost::Python 库来处理这个问题。它几乎可以让您导出任何您需要的东西 - 类、运算符,甚至是多个重载方法。

唯一的问题是,这个库非常大,而且它是 non-header-only Boost 库之一,所以您需要弄清楚如何用您的项目构建它,这对于从未使用过 Boost 的人(比如我自己)。

我不知道这个库到底做了什么,也许它只是自动化了前面方法中描述的相同的事情。所以我不确定它是否减少了额外包装器的级别,或者只是简单地为您完成所有硬包装工作,但它完成了我需要完成的工作。

更快的方法

幸运的是我遇到了一个替代方案——pybind11。这是一个相对较小的库,与 Boost::Python 和 header-only 做同样的事情。它有很好的文档并且易于使用。它被称为 pybind11 因为它最初是为了支持 C++11,但它目前支持 C++14 和实验性的 C++17,但我将它与 C++ 一起使用17个项目,目前没有发现问题。

我还不确定哪种方法最适合我的项目,但现在,我使用 pybind11,只是为了在项目开发过程中更容易。