學習是一個累積的過程。在這個過程中,我們不僅要學習新的知識,還需要將以前學到的知識進行回顧總結。
前面講述了Python使用ctypes直接調用動態庫和使用Python的C語言API封裝C函數, C++寫python擴展模塊有很多種方式,我選擇的是boost.python來編寫的,感覺這個要比其他的方式要簡單很多,本文概述方便封裝C++類給Python使用的boost_python庫。
:
sudo aptitude install libboost-python-dev
示例
下面代碼簡單實現了一個普通函數maxab()和一個Student類:
#include <iostream> #include <string> int maxab(int a, int b) { return a>b?a:b; } class Student { private: int age; std::string name; public: Student() {} Student(std::string const& _name, int _age) { name=_name; age=_age; } static void myrole() { std::cout << "I'm a student!" << std::endl; } void whoami() { std::cout << "I am " << name << std::endl; } bool operator==(Student const& s) const { return age == s.age; } bool operator!=(Student const& s) const { return age != s.age; } };
使用boost.python庫封裝也很簡單,如下代碼所示:
#include <Python.h> #include <boost/python.hpp> #include <boost/python/suite/indexing/vector_indexing_suite.hpp> #include <vector> #include "student.h" using namespace boost::python; BOOST_PYTHON_MODULE(student) { // This will enable user-defined docstrings and python signatures, // while disabling the C++ signatures scope().attr("__version__") = "1.0.0"; scope().attr("__doc__") = "a demo module to use boost_python."; docstring_options local_docstring_options(true, false, false); def( "maxab", &maxab, "return max of two numbers.\n" ); class_<Student>("Student", "a class of student") .def(init<>()) .def(init<std::string, int>()) // methods for Chinese word segmentation .def( "whoami", &Student::whoami, "method's doc string..." ) .def( "myrole", &Student::myrole, "method's doc string..." ) .staticmethod("myrole"); // 封裝STL class_<std::vector<Student> >("StudentVec") .def(vector_indexing_suite<std::vector<Student> >()) ; }
上述代碼還是include了Python.h文件,如果不include的話,會報錯誤:
wrap_python.hpp:50:23: fatal error: pyconfig.h: No such file or directory
編譯
編譯以上代碼有兩種方式,一種是在命令行下面直接使用g++編譯:
g++ -I/usr/include/python2.7 -fPIC wrap_student.cpp -lboost_python -shared -o student.so
首先指定Python.h的路徑,如果是Python 3的話就要修改為相應的路徑,編譯wrap_student.cpp要指定-fPIC參數,鏈接(-lboost_python)生成動態庫(-shared)。 生成的student.so動態庫就可以被python直接import使用了
In [1]: import student In [2]: student.maxab(2, 5) Out[2]: 5 In [3]: s = student.Student('Tom', 12) In [4]: s.whoami() I am Tom In [5]: s.myrole() I'm a student!
另外一直方法是用python的setuptools編寫setup.py腳本:
#!/usr/bin/env python from setuptools import setup, Extension setup(name="student", ext_modules=[ Extension("student", ["wrap_student.cpp"], libraries = ["boost_python"]) ])
然后執行命令編譯:
python setup.py build or sudo python setup.py install
學習筆記整理於猿人學教程