你将学到什么

  • 在Python中调用C++代码时的传参问题

基础类型

Python的字符串是常量,所以C++函数参数中的std::string &必须为const

修改源文件(main.cpp)

#include <iostream>
#include <boost/python.hpp>
#include "boost_wrapper.h" using namespace boost::python;
using namespace boost::python::detail; 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;
}

Python脚本如下(build/zoo.py)

import boost

def show():
boost.add(2, 4)
boost.xstr("fwd") if __name__ == '__main__':
pass

导出头文件如下(include/boost_wrapper.h)

#pragma once

#include <string>

void add(int x, int y);
void xstr(std::string const &x);

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

#include <iostream>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include "boost_wrapper.h" using namespace boost::python;
using namespace boost::python::detail; void add(int x, int y)
{
std::cout << "add: " << x + y << std::endl;
} void xstr(std::string const &x)
{
std::cout << "string: " << x << std::endl;
} BOOST_PYTHON_MODULE_INIT(boost)
{
def("add", add);
def("xstr", xstr);
}

标准库

修改源文件(main.cpp)

#include <iostream>
#include <boost/python.hpp>
#include "boost_wrapper.h" using namespace boost::python;
using namespace boost::python::detail; 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;
}

方式一

这种方式主要使用vector_indexing_suite定义一个新的Vector类型XVec

Python脚本如下(build/zoo.py)

import boost

def show():
l = boost.XVec()
l.append(2)
l.append(3)
l.append(4)
boost.show_list(l)
for i in l:
print(i) if __name__ == '__main__':
pass

导出头文件如下(include/boost_wrapper.h)

#pragma once

#include <vector>

void show_list(std::vector<int> &v);

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

#include <iostream>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include "boost_wrapper.h" using namespace boost::python;
using namespace boost::python::detail; void show_list(std::vector<int> &v)
{
for (auto item : v)
{
std::cout << item << " ";
}
std::cout << std::endl;
v.push_back(7);
} BOOST_PYTHON_MODULE_INIT(boost)
{
class_<std::vector<int> >("XVec").def(vector_indexing_suite<std::vector<int> >());
def("show_list", show_list);
}

方式二

这种方式主要是通过boost :: python :: converter :: registry :: push_back函数来注册自定义转换函数,主要实现两个函数convertible(用于检测Python侧传入的对象是否符合转换条件,比如是不是迭代器、里面的元素类型是不是对的等,这边只是简单实现下)和construct(提取Python侧传入的对象元素,然后构造C++侧的对象,这边也只是简单实现了下),高级实现方式可以参考cctbx_projectscitbx/array_family/boost_python/regress_test_ext.cppscitbx/boost_python/container_conversions.h文件,不过参数必须是右值(注意函数参数的const修饰符不能删)

Python脚本如下(build/zoo.py)

import boost

def show():
boost.show_list([2,3,4]) if __name__ == '__main__':
pass

导出头文件如下(include/boost_wrapper.h)

#pragma once

#include <vector>

void show_list(std::vector<int> const &v);

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

#include <iostream>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/to_python_converter.hpp>
#include "boost_wrapper.h" using namespace boost::python;
using namespace boost::python::detail; void show_list(std::vector<int> const &v)
{
for (auto item : v)
{
std::cout << item << " ";
}
std::cout << std::endl;
} template<class ContainerType>
class from_python_list
{
public:
from_python_list()
{
boost::python::converter::registry::push_back(&convertible, &construct, boost::python::type_id<ContainerType>());
} static void* convertible(PyObject *obj_ptr)
{
if (!(PyList_Check(obj_ptr)
|| PyTuple_Check(obj_ptr)
|| PyIter_Check(obj_ptr)
|| PyRange_Check(obj_ptr)
|| (PyObject_HasAttrString(obj_ptr, "__len__") && PyObject_HasAttrString(obj_ptr, "__getitem__"))))
return 0; return obj_ptr;
} static void construct(PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data* data)
{
boost::python::handle<> obj_iter(PyObject_GetIter(obj_ptr));
void *storage = ((boost::python::converter::rvalue_from_python_storage<ContainerType>*)data)->storage.bytes;
new (storage) ContainerType();
data->convertible = storage;
ContainerType &result = *((ContainerType*)storage); while (true)
{
boost::python::handle<> py_hdl(boost::python::allow_null(PyIter_Next(obj_iter.get())));
if (PyErr_Occurred())
boost::python::throw_error_already_set();
if (!py_hdl.get())
break;
boost::python::object py_obj(py_hdl);
boost::python::extract<typename ContainerType::value_type> obj(py_obj);
result.push_back(obj);
}
}
}; BOOST_PYTHON_MODULE_INIT(boost)
{
def("show_list", show_list);
from_python_list<std::vector<int>>();
}

Boost Python学习笔记(四)的更多相关文章

  1. Boost Python学习笔记(五)

    你将学到什么 在C++中调用Python代码时的返回值问题 基础类型 修改Python脚本(build/zoo.py) def rint(): return 2 def rstr(): return ...

  2. Boost Python学习笔记(二)

    你将学到什么 如何在Python中调用C++代码 如何在C++中调用Python代码 在Python中调用C++代码 首先定义一个动物类(include/animal.h) #pragma once ...

  3. Boost Python学习笔记(三)

    你将学到什么 在C++中调用Python代码时的传参问题 基础类型 继续使用前面的项目,但是先修改下Python脚本(zoo.py),添加Add和Str函数,分别针对整数.浮点数和字符串参数的测试 d ...

  4. Python学习笔记(四)Python函数的参数

    Python的函数除了正常使用的必选参数外,还可以使用默认参数.可变参数和关键字参数. 默认参数 基本使用 默认参数就是可以给特定的参数设置一个默认值,调用函数时,有默认值得参数可以不进行赋值,如: ...

  5. Python学习笔记四

    一.装饰器 1.知识储备 函数对象 函数可以被引用 函数可以当参数传递 返回值可以是函数 可以当作容器的元素 def func1(): print (666) def func2(): print ( ...

  6. Python学习笔记四:面向对象编程

    一:定义类并创建实例 Python中定义类,通过class关键字,类名开头大写,参数列表为所继承的父类.如果没有需要明确继承的类,则继承object. 使用类来创建对象,只需 类名+() 形式即可,p ...

  7. python学习笔记(四) 思考和准备

    一.zip的坑 zip()函数接收多个可迭代数列,将数列中的元素重新组合,在3.0中返回迭代器指向 数列首地址,在3.0以下版本返回List类型的列表数列.我用的是3.5版本python, 所以zip ...

  8. python学习笔记(四):函数

    一.函数是什么? 函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,编程中的函数在英文中也有很多不同的叫法.在BASIC中叫做subroutine(子过程或子程序),在Pasc ...

  9. Boost Python学习笔记(一)

    开发环境搭建 下载源码 boost_1_66_0.tar.gz 生成编译工具 # tar axf boost_1_66_0.tar.gz # cd boost_1_66_0 # yum install ...

随机推荐

  1. Codeforces 463D Gargari and Permutations:隐式图dp【多串LCS】

    题目链接:http://codeforces.com/problemset/problem/463/D 题意: 给你k个1到n的排列,问你它们的LCS(最长公共子序列)是多长. 题解: 因为都是1到n ...

  2. 洛谷p3369 treap

    这是一个treap裸题,还可以用splay,替罪羊树,线段树等等写 treap是树和堆结合,可以方便的在O(log(n))期望时间内进行以下操作,因此treap又叫做名次树 插入x数 删除x数(若有多 ...

  3. bzoj-2458 2458: [BeiJing2011]最小三角形(计算几何+分治)

    题目链接: 2458: [BeiJing2011]最小三角形 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1101  Solved: 380 Des ...

  4. 微信非全屏播放设置(仅Iphone)

    由于微信X5内核强制视频全屏,用X5自带内核播放,一般内嵌视频打开播放就会被全屏. ihpone里面可以通过设置 x-webkit-airplay="true" webkit-pl ...

  5. Code Chef - Chef and Graph Queries

    传送门 题目大意 给定一个$n$个点$m$条边的无向图$(n,m\leq 200000)$. 有$q$每次询问$(q\leq 200000)$,每次给定一个区间$L,R$,求仅保留编号$\in[L,R ...

  6. bzoj3573米特运输

    题意: 给定一棵树上的边和点权 改动点权使得每个父节点u容量为子节点容量的d[u](子节点个数)倍 考察点: 1.这是一道语文题 2.点权很大 直接算会爆 有一种优化办法:取log(醉 这是什么优化) ...

  7. BZOJ5281:[Usaco2018 Open]Talent Show

    我对二分的理解:https://www.cnblogs.com/AKMer/p/9737477.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...

  8. 洛谷【P1480】A/B Problem

    题目传送门:https://www.luogu.org/problemnew/show/P1480 高精除低精板子题,灵性地回忆一下小学时期列竖式的草稿纸即可. 时间复杂度:\(O(len)\) 空间 ...

  9. LInux在线安装JDK

    1.查找Java相关列表: [root@localhost ~]# yum -y list java* 2.使用root用户安装安装时提醒必须使用root用户,sudo都不行. [root@local ...

  10. Ajax的包装

    /** * Created by Administrator on 2016/12/27. *//** * 创建XMLHttpRequest对象 * @param _method 请求方式: post ...