zoukankan      html  css  js  c++  java
  • Boost Python学习笔记(四)

    你将学到什么

    • 在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>>();
    }
    
  • 相关阅读:
    交叉工具链的搭建方法(测试成功)
    使用samba实现linux与windows共享(测试成功)
    sd卡脱机烧写系统的方法(测试成功)
    Navicat连接SQLServer未发现数据源名并且未指定默认驱动程序
    使用docker rmi 批量删除docker镜像
    删除镜像docker rmi IMAGE ID提示image is referenced in multiple repositories
    Linux下,改过/etc/profile文件导致ls vi等命令不能使用解决方法
    安装openssl-dev 报错E: Unable to locate package openssl-dev
    zabbix监控redis命中率---张庆沉笔记
    布局之BFC
  • 原文地址:https://www.cnblogs.com/silvermagic/p/9087509.html
Copyright © 2011-2022 走看看