使用Py++生成的代码作为Python扩展

5 投票
3 回答
6549 浏览
提问于 2025-04-15 18:41

我需要把一个现有的C++库包装一下,以便在Python中使用。在看过关于如何选择合适的方法将C++包装成Python可用的答案后,我决定使用Py++。

我按照Py++的教程,使用了教程中的文件,得到了我预期的输出在generated.cpp中,但我还没搞明白怎么才能把生成的代码用作可以在Python中导入的扩展。我知道现在得编译这些代码,但用什么工具呢?我是不是应该用bjam

3 个回答

1

我写了一个简单的makefile,内容如下:

GNUmakefile:

PYTHON_INC=$(shell python-config --includes)
PYTHON_LIBS=$(shell python-config --libs)
BOOST_LIBS=-lboost_python

all:
    g++ -W -Wall $(PYTHON_INC) $(PYTHON_LIBS) $(BOOST_LIBS) -fPIC -shared generated.cpp -o hw.so

然后我把生成的.so文件加载到ipython里,想试试它的效果:

In [1]: import hw
In [2]: a = hw.animal('zebra')
In [3]: a.name()
Out[3]: 'zebra'
4

以下的回答是由Roman Yakovenko在Python C++-sig邮件列表上提供的;我在这里稍作修改后发布,目的是为了帮助Stack Overflow社区的朋友们。

我还没有完全理解这个回答,但我觉得它给了我一个正确的方向。


在你生成代码之后,接下来需要编译它。为此,你可以使用你喜欢的构建系统。我个人只用bjam来编译boost。之后,我更喜欢在Windows和Linux上使用scons。

下面是一个sconstruct文件的例子,这个文件用于编译Py++的一个单元测试(这也是生成的代码哦 :-)):

import sys
env = Environment()

if 'linux' not in sys.platform:
   env['MSVS'] = {'VERSION': ''}
   env['MSVS_VERSION'] = ''
   Tool('msvc')(env)

t = env.SharedLibrary(
    target=r'abstract_classes',
    source=[r'/home/roman/language-binding/sources/pyplusplus_dev/unittests/temp/abstract_classes.cpp'],
    LIBS=[r"boost_python"],
    LIBPATH=[r"", r"/home/roman/include/libs"],
    CPPPATH=[
        r"/home/roman/boost_svn",
        r"/usr/include/python2.6",
        r"/home/roman/language-binding/sources/pyplusplus_dev/unittests/temp",
        r"/home/roman/language-binding/sources/pyplusplus_dev/unittests/data",
        r"/home/roman/boost_svn"
    ],
    CCFLAGS=[  ],
    SHLIBPREFIX='',
    SHLIBSUFFIX='.so'
)

因为你的代码生成器是用Python写的,所以你可以在Py++停止的地方继续,生成你喜欢的“make”文件。你甚至可以做得更进一步。Py++的测试会生成代码、编译、加载新的模块并测试功能。所有这些操作都是在一个独立的进程中完成的。

6

Py++ 是一个工具,它可以帮你生成一些代码,这些代码和 boost::python 一起使用,目的是在你的应用程序中创建 Python 的入口点。

假设你在使用 Py++ 的过程中一切顺利,你需要下载 Boost 框架,然后把 Boost 的包含目录和 boost::python 的库添加到你的项目中,接着用 Py++ 生成的 cpp 文件进行编译。

你可以选择任何你喜欢的构建系统来处理你的项目,但 Boost 是用 bjam 构建的。你需要决定是要静态库还是动态库的 boost python,然后按照 这里 的说明来构建 Boost。

如果你是在 Windows 上,你需要把生成的库的扩展名从 .dll 改成 .pyd。并且,这个项目必须是一个库项目,不能是可执行文件。

然后,把这个 pyd 文件放到你的机器上 Python 可以找到的地方,接着打开 Python,执行 import [你的库名],希望一切都能正常工作。

最后要注意的是,在这个宏中生成的 cpp 文件里的名字:

BOOST_PYTHON_MODULE( -name- )

必须和你的项目名字完全一致,否则 Python 会报错。

我在不到一个月前刚经历过这一切,所以我知道这其中的困惑。

为了让我的 Python 扩展在构建库和测试时更容易使用,我选择在我的构建环境中自己构建 boost::python 和 Python。这样,pyd 文件就能放在我想要的位置,用户不需要安装 Python 就可以使用我的扩展。不过,这可能对你来说有点过于复杂。

补充说明:如果你希望你的扩展在其他机器上容易安装和编译,可以看看 Python 的 setuptools。只需几行简单的代码,你就可以让 Python 为你编译和安装你的包。不过,有一个缺点,就是它和那些喜欢在 Visual Studio 中开发的人不太兼容。

撰写回答