你将学到什么

  • 在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. JS中不同类型的值比较问题

    我们比较数据的时候大多是以下两种情况: 3 > 4 ; "m" > "n" ; 但有时候可能会出现比较符号两侧的数据类型不相同的场景,例如 5 &g ...

  2. JQuery- JQuery学习

    jQuery与JavaScript加载页面的区别 1.JavaScript传统的方式页面加载会存在覆盖问题,加载比jQuery慢(整个页面加载完毕<包含里面的其他内容,比如图片>) 2.j ...

  3. AJAX+json+jquery实现预加载瀑布流布局

    宽度是一定的高度不定的瀑布流布局 也可以说是无缝拼图 当浏览器滚动到底部时候自动加载图片 加载的图片地址用json 在img.js里 ,还有正在加载动画是用 css3制作的 在ff等支持css3可以显 ...

  4. C#实现网站登录

    public class HTMLHelper    {        /// <summary>           /// 获取CooKie          /// /// < ...

  5. 智课雅思词汇---十四、ante,anti不仅是词根还是前缀

    智课雅思词汇---十四.ante,anti不仅是词根还是前缀 一.总结 一句话总结:来源于拉丁语 ante 前.词根ant 为 anti 的变体.ante,anti不仅是词根还是前缀. 词根:ante ...

  6. python3 字符串属性(三)

    maketrans 和 translate的用法(配合使用) 下面是python的英文用法解释 maketrans(x, y=None, z=None, /) Return a translation ...

  7. 【leetcode】Construct Binary Tree from Inorder and Postorder Traversal

    Given inorder and postorder traversal of a tree, construct the binary tree. Note:You may assume that ...

  8. 【遍历二叉树】07恢复二叉搜索树【Recover Binary Search Tree】

    开一个指针数组,中序遍历这个二叉搜索树,将节点的指针依次保存在数组里, 然后寻找两处逆序的位置, 中序便利里BST得到的是升序序列 ++++++++++++++++++++++++++++++++++ ...

  9. pthread_cond_wait()用法分析

    很久没看APUE,今天一位朋友问道关于一个mutex的问题,又翻到了以前讨论过的东西,为了不让自己忘记,把曾经的东西总结一下. 先大体看下网上很多地方都有的关于pthread_cond_wait()的 ...

  10. Qt Quick中的信号与槽

    在QML中,在Qt Quick中,要想妥善地处理各种事件,肯定离不开信号与槽,本博的主要内容就是整理Qt 中的信号与槽的内容. 1. 链接QML类型的已知信号 QML中已有类型定义的信号分为两类:一类 ...