你将学到什么

  • 在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. Linux - xshell上传文件报错乱码

    xshell上传文件报错乱码,解决方法 rz -be 回车 下载sz  filename

  2. 分享知识-快乐自己:三种代理(静态、JDK、CGlib 代理)

    1):代理模式(静态代理)点我下载三种模式源码 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由 业务实现类.业务代理类 两部分组成 ...

  3. SpringBoot_03_依赖本地jar

    一.方法一 1.说明 用Maven打到本地仓库,然后直接引入 2.参考资料 Springboot 打Jar包,Maven完美解决本地Jar包自动打入Springboot Jar包中 3.执行maven ...

  4. Java_注解_00_资源贴

    1.Java注解教程:自定义注解示例,利用反射进行解析 2. (1)深入理解Java:注解(Annotation)基本概念 (2)深入理解Java:注解(Annotation)自定义注解入门 (3)深 ...

  5. uoj problem 11 ydc的大树

    题目大意: 给定一颗黑白树.允许删除一个白点.最大化删点后无法与删点前距自己最远的黑点连通的黑点个数.并求出方案数. 题解: 这道题很棒棒啊. 一开始想了一个做法,要用LCT去搞,特别麻烦而且还是\( ...

  6. 【C&C++】查看代码运行时间

    查看代码运行时间有助于更好地优化项目代码 1. Windows平台 windows平台下有两种方式,精度有所不同,都需要包含<windows.h>头文件 1) DWORD GetTickC ...

  7. DEBUG命令详细说明

    启动DEBUG 1.打开Windows命令窗口 在Windows 95/98的环境中,打开命令窗口的步骤为:点击“开始”→“运行”,输入“command”命令: 在WindowsXP及WIN7的环境中 ...

  8. Azure CLI下载Azure Storage Container内的所有文件

    在某些场景下,客户需要把Azure Storage的某一个container内的内容都下载到本地.当然采用PowerShell可以定时的进行下载的动作,但有时客户的环境是Linux或MacOS,这时需 ...

  9. SYS/BIOS实例分析

    SYS/BIOS简介 SYS/BIOS是一个可扩展的实时内核(或者说是操作系统),其提供了许多模块化的APIs(应用程序接口),支持抢占式多线程,硬件抽象,实时分析和配置工具,其设计目的是为了最大限度 ...

  10. SQL常用语法及规则-表格的操作

    一.规则和标准 1)每一行SQL语句结尾,加分号: 2)所创建的对象,名字用反引号(不是引号,与~同一个键): 3)一般关键字或保留字要大写: 4)两个中划线 + 空格(-- ),后面的语句为注释语句 ...