首先定義一個動物類(include/animal.h)python
#pragma once #include <string> class Animal { public: Animal(std::string name); virtual ~Animal(); virtual void call(); virtual void move(); void eat(std::string food); protected: std::string name_; };
其實現代碼以下(src/animal.cpp)ios
#include <iostream> #include "animal.h" Animal::Animal(std::string name):name_(name) { } Animal::~Animal() { } void Animal::call() { std::cout << name_ << ": call" << std::endl; } void Animal::move() { std::cout << name_ << ": moving" << std::endl; } void Animal::eat(std::string food) { std::cout << name_ << ": eat " << food << std::endl; }
接着編寫其導出代碼(include/boost_wrapper.h)編程
#pragma once #include <boost/python/wrapper.hpp> #include "animal.h" class AnimalWrap: public Animal, public boost::python::wrapper<Animal> { public: AnimalWrap(std::string name); virtual ~AnimalWrap(); void call(); void move(); };
其導出實現以下(src/boost_wrapper.cpp)app
#include <boost/python/module.hpp> #include <boost/python/class.hpp> #include "boost_wrapper.h" using namespace boost::python; using namespace boost::python::detail; AnimalWrap::AnimalWrap(std::string name):Animal(name) { } AnimalWrap::~AnimalWrap() { } void AnimalWrap::call() { if (override func = this->get_override("call")) func(); Animal::call(); } void AnimalWrap::move() { if (override func = this->get_override("move")) func(); Animal::move(); } BOOST_PYTHON_MODULE_INIT(boost) { class_<AnimalWrap, boost::noncopyable>("Animal", init<std::string>()) .def("call", &Animal::call) .def("move", &Animal::move) .def("eat", &Animal::eat); }
最後編寫CMakeLists.txtide
cmake_minimum_required(VERSION 2.8) project(boost) set(CMAKE_CXX_FLAGS "-Wall -g") ### 此處的動態庫名必須和BOOST_PYTHON_MODULE()中定義的保持一致,即最後生成的庫必須名爲boost.so file(GLOB SRC "src/*.cpp") add_library(boost SHARED ${SRC}) set_target_properties(boost PROPERTIES PREFIX "") #dependencies INCLUDE(FindPkgConfig) pkg_check_modules(PYTHON REQUIRED python) include_directories(include /usr/local/include ${PYTHON_INCLUDE_DIRS}) link_directories(/usr/local/lib ${PYTHON_LIBRARY_DIRS}) target_link_libraries(boost boost_python)
項目最終目錄結構測試
# tree . . ├── build ├── CMakeLists.txt ├── include │ ├── animal.h │ └── boost_wrapper.h └── src ├── animal.cpp └── boost_wrapper.cpp 3 directories, 5 files
編譯ui
# cd build # cmake .. # make
編寫測試文件(build/zoo.py)this
import boost def show(): wolf = boost.Animal("wolf") wolf.eat("beef") goat = boost.Animal("gota") goat.eat("grass") if __name__ == '__main__': show()
執行測試spa
# cd build # python zoo.py wolf: eat beef gota: eat grass
在上個項目的根目錄添加源文件(main.cpp)設計
#include <iostream> #include <boost/python.hpp> using namespace boost::python; int main() { Py_Initialize(); if (!Py_IsInitialized()) { std::cout << "Initialize failed" << std::endl; return -1; } try { object sys_module = import("sys"); str module_directory("."); sys_module.attr("path").attr("insert")(1, module_directory); object module = import("zoo"); module.attr("show")(); } catch (const error_already_set&) { PyErr_Print(); } Py_Finalize(); return 0; }
修改CMakeLists.txt
cmake_minimum_required(VERSION 2.8) project(boost) set(CMAKE_CXX_FLAGS "-Wall -g") ### 此處的動態庫名必須和BOOST_PYTHON_MODULE()中定義的保持一致,即最後生成的庫必須名爲boost.so file(GLOB SRC "src/*.cpp") add_library(boost SHARED ${SRC}) set_target_properties(boost PROPERTIES PREFIX "") add_executable(core main.cpp) #dependencies INCLUDE(FindPkgConfig) pkg_check_modules(PYTHON REQUIRED python) include_directories(include /usr/local/include ${PYTHON_INCLUDE_DIRS}) link_directories(/usr/local/lib ${PYTHON_LIBRARY_DIRS}) target_link_libraries(boost boost_python) target_link_libraries(core boost ${PYTHON_LIBRARIES})
編譯並執行測試
# cd build # cmake .. # make # ./core wolf: eat beef gota: eat grass
考慮這樣一個需求,咱們要展現一個動物園中的動物,可是動物的種類和個數都不固定,這就致使咱們動物園的show
方法須要常常變更,有什麼辦法能夠避免程序的反覆編譯呢?一種方式就是使用配置文件,將須要展現的動物寫入配置文件,而後動物園的show
方法經過解析配置文件來生成須要展現的內容;另外一種方式就是經過Python腳原本實現,由於Python腳本不須要編譯,相比於配置文件的方式,Python腳本的方式不須要設計配置文件格式,也不須要實現複雜的解析邏輯,使用起來更加靈活。
在上面的例子中,咱們使用Python腳本實現了本來應該在main.cpp
中實現的show
方法,而後在main.cpp
中調用它,後面若是有改動咱們直接修改Python腳本便可,無需重編程序。