如何组织Python / Boost Python项目

4 投票
2 回答
783 浏览
提问于 2025-04-16 10:28

我有一个Python项目,我想用Boost::Python这个工具来和一些C++库进行连接。我想知道其他人是怎么把他们的Python、Boost::Python和C++代码在同一个项目里组织起来的。

这里的“组织”指的是文件和文件夹的结构、构建过程等等。

2 个回答

0

我不能直接给你建议,不过有一个叫做paludis的包管理工具是为Gentoo系统设计的,它可以做到你想要的事情。根据我所知道的,开发这个工具的人非常有能力,所以它的源代码可能是个不错的学习例子。

不过我个人不太推荐使用Boost Python。听说它相比其他绑定工具,比如cython、SWIG或者SIP,速度很慢,而且占用内存也比较多。

1

接下来,pif指的是Python接口。首先,我有一个通用的头文件,叫做conv_pif.hpp,里面包含了Boost库和C++标准库的头文件等。然后,对于每个Boost Python模块,我有一个文件(这里对应的例子模块是genocpp),文件名是string_pif.cpp,其中的string大致对应模块的名称。

****************************************************************************************
geno_pif.cpp
****************************************************************************************
#include "conv_pif.hpp"
#include <boost/python.hpp>
#include "geno.hpp"

void export_cppvec_conv();

void export_geno()
{
  boost::python::def("write_geno_table_affy6_to_file", write_geno_table_affy6_to_file);
}

BOOST_PYTHON_MODULE(genocpp)
{
  export_geno();
  export_cppvec_conv();
}
*****************************************************************************************

函数export_cppvec_conv是一个(模板)转换器,用于在C++的向量和Python的列表之间转换。实际的转换器在文件cppvec_conv_pif.cpp中。特别地,这里定义了export_cppvec_conv,它使用模板实例化,所以我可以不在geno_pif.cpp中包含它。为了说明,export_cppvec_conv的内容如下,其中cppvec_to_python_list和cppvec_from_python_list是在cppvec_conv_pif.cpp的主体中定义的。

******************************************
cppvec_conv_pif.cpp (extract)
******************************************
void export_cppvec_conv()
{
  boost::python::to_python_converter<vector<double>, cppvec_to_python_list<double> >();
  cppvec_from_python_list<double>();

  boost::python::to_python_converter<vector<int>, cppvec_to_python_list<int> >();
  cppvec_from_python_list<int>();

  boost::python::to_python_converter<vector<string>, cppvec_to_python_list<string> >();
  cppvec_from_python_list<string>();
}
******************************************

可以根据需要为genocpp模块添加任意数量的转换器。当然,我还有geno函数的头文件在geno.hpp中。最后,我有一个Scons文件,它把所有东西链接在一起。

******************************************
Sconstruct
******************************************
#!/usr/bin/python

import commands, glob, os

# Common file, for both executables and Python Interface
common_files = """geno print"""

def pyversion():
    pystr = commands.getoutput('python -V')
    version = pystr.split(' ')[1]
    major, minor = version.split('.')[:2]
    return major + '.' + minor

common_base = Split(common_files)
common = [f + ".cpp" for f in common_base]

# For Python interface only
pif_conv = Split("cppvec_conv cppmap_conv cppset_conv")
pif_conv_files = [t+"_pif.cpp" for t in pif_conv]

pif = Split("geno")
pif_files = [t+"_pif.cpp" for t in pif]

# Boost Python Environment
boost_python_env = Environment(
    CPPPATH=["/usr/include/python"+pyversion(), "."],
    CXXFLAGS='-ftemplate-depth-100 -fPIC -Wall -Werror -pedantic -pipe -O3 -ffast-math -march=opteron',
    #CXXFLAGS='-ftemplate-depth-100 -fPIC -Wall -pedantic -O0 -g',
    CPPDEFINES=['BOOST_PYTHON_DYNAMIC_LIB'],
    LIBPATH=["/usr/lib/python"+pyversion()+"/config"],
    LIBS=["python"+pyversion(), "m", "boost_python"],
    SHLIBPREFIX="", #gets rid of lib prefix
    SHOBJSUFFIX = ".bpo"
)

boost_python_env.SharedLibrary(target='genocpp', source = common + pif_conv_files + pif_files)

在这个例子中,只有一个模块,所以pif_files里只有geno_pif.cpp。否则,我会选择我想要的模块。嗯,也许上传一个可以工作的例子会更简单。如果有人对更多细节感兴趣,我可以编辑一下这个内容吗?

祝好,Faheem

撰写回答