Boost Python学习笔记(二)

你将学到什么

  • 如何在Python中调用C++代码
  • 如何在C++中调用Python代码

在Python中调用C++代码

首先定义一个动物类(include/animal.h)

1#pragma once 2 3#include <string> 4 5class Animal 6{ 7public: 8 Animal(std::string name); 9 virtual ~Animal(); 10 11 virtual void call(); 12 virtual void move(); 13 void eat(std::string food); 14 15protected: 16 std::string name_; 17};

其实现代码如下(src/animal.cpp)

1#include <iostream> 2#include "animal.h" 3 4Animal::Animal(std::string name):name_(name) 5{ 6} 7 8Animal::~Animal() 9{ 10} 11 12void Animal::call() 13{ 14 std::cout << name_ << ": call" << std::endl; 15} 16 17void Animal::move() 18{ 19 std::cout << name_ << ": moving" << std::endl; 20} 21 22void Animal::eat(std::string food) 23{ 24 std::cout << name_ << ": eat " << food << std::endl; 25}

接着编写其导出代码(include/boost_wrapper.h)

1#pragma once 2 3#include <boost/python/wrapper.hpp> 4#include "animal.h" 5 6class AnimalWrap: public Animal, public boost::python::wrapper<Animal> 7{ 8public: 9 AnimalWrap(std::string name); 10 virtual ~AnimalWrap(); 11 12 void call(); 13 void move(); 14};

其导出实现如下(src/boost_wrapper.cpp)

1#include <boost/python/module.hpp> 2#include <boost/python/class.hpp> 3#include "boost_wrapper.h" 4 5using namespace boost::python; 6using namespace boost::python::detail; 7 8AnimalWrap::AnimalWrap(std::string name):Animal(name) 9{ 10} 11 12AnimalWrap::~AnimalWrap() 13{ 14} 15 16void AnimalWrap::call() 17{ 18 if (override func = this->get_override("call")) 19 func(); 20 Animal::call(); 21} 22 23void AnimalWrap::move() 24{ 25 if (override func = this->get_override("move")) 26 func(); 27 Animal::move(); 28} 29 30BOOST_PYTHON_MODULE_INIT(boost) 31{ 32 class_<AnimalWrap, boost::noncopyable>("Animal", init<std::string>()) 33 .def("call", &Animal::call) 34 .def("move", &Animal::move) 35 .def("eat", &Animal::eat); 36}

最后编写CMakeLists.txt

1cmake_minimum_required(VERSION 2.8) 2project(boost) 3 4set(CMAKE_CXX_FLAGS "-Wall -g") 5 6### 此处的动态库名必须和BOOST_PYTHON_MODULE()中定义的保持一致,即最后生成的库必须名为boost.so 7file(GLOB SRC "src/*.cpp") 8add_library(boost SHARED ${SRC}) 9set_target_properties(boost PROPERTIES PREFIX "") 10 11#dependencies 12INCLUDE(FindPkgConfig) 13pkg_check_modules(PYTHON REQUIRED python) 14include_directories(include /usr/local/include ${PYTHON_INCLUDE_DIRS}) 15link_directories(/usr/local/lib ${PYTHON_LIBRARY_DIRS}) 16target_link_libraries(boost boost_python)

项目最终目录结构

1# tree . 2. 3├── build 4├── CMakeLists.txt 5├── include 6│ ├── animal.h 7│ └── boost_wrapper.h 8└── src 9 ├── animal.cpp 10 └── boost_wrapper.cpp 11 123 directories, 5 files

编译

1# cd build 2# cmake .. 3# make

编写测试文件(build/zoo.py)

1import boost 2 3def show(): 4 wolf = boost.Animal("wolf") 5 wolf.eat("beef") 6 goat = boost.Animal("gota") 7 goat.eat("grass") 8 9if __name__ == '__main__': 10 show()

执行测试

1# cd build 2# python zoo.py 3wolf: eat beef 4gota: eat grass

在C++中调用Python代码

在上个项目的根目录添加源文件(main.cpp)

1#include <iostream> 2#include <boost/python.hpp> 3 4using namespace boost::python; 5 6int main() 7{ 8 Py_Initialize(); 9 if (!Py_IsInitialized()) 10 { 11 std::cout << "Initialize failed" << std::endl; 12 return -1; 13 } 14 15 try 16 { 17 object sys_module = import("sys"); 18 str module_directory("."); 19 sys_module.attr("path").attr("insert")(1, module_directory); 20 object module = import("zoo"); 21 module.attr("show")(); 22 } 23 catch (const error_already_set&) 24 { 25 PyErr_Print(); 26 } 27 Py_Finalize(); 28 return 0; 29}

修改CMakeLists.txt

1cmake_minimum_required(VERSION 2.8) 2project(boost) 3 4set(CMAKE_CXX_FLAGS "-Wall -g") 5 6### 此处的动态库名必须和BOOST_PYTHON_MODULE()中定义的保持一致,即最后生成的库必须名为boost.so 7file(GLOB SRC "src/*.cpp") 8add_library(boost SHARED ${SRC}) 9set_target_properties(boost PROPERTIES PREFIX "") 10add_executable(core main.cpp) 11 12#dependencies 13INCLUDE(FindPkgConfig) 14pkg_check_modules(PYTHON REQUIRED python) 15include_directories(include /usr/local/include ${PYTHON_INCLUDE_DIRS}) 16link_directories(/usr/local/lib ${PYTHON_LIBRARY_DIRS}) 17target_link_libraries(boost boost_python) 18target_link_libraries(core boost ${PYTHON_LIBRARIES})

编译并执行测试

1# cd build 2# cmake .. 3# make 4# ./core 5wolf: eat beef 6gota: eat grass

总结

考虑这样一个需求,我们要展示一个动物园中的动物,但是动物的种类和个数都不固定,这就导致我们动物园的show方法需要经常变动,有什么办法可以避免程序的反复编译呢?一种方式就是使用配置文件,将需要展示的动物写入配置文件,然后动物园的show方法通过解析配置文件来生成需要展示的内容;另一种方式就是通过Python脚本来实现,因为Python脚本不需要编译,相比于配置文件的方式,Python脚本的方式不需要设计配置文件格式,也不需要实现复杂的解析逻辑,使用起来更加灵活。

在上面的例子中,我们使用Python脚本实现了原本应该在main.cpp中实现的show方法,然后在main.cpp中调用它,后面如果有改动我们直接修改Python脚本即可,无需重编程序。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )