美文网首页
C++和Python的混合编程-C++数据类型的导出和调用

C++和Python的混合编程-C++数据类型的导出和调用

作者: JasonLiThirty | 来源:发表于2019-02-11 22:12 被阅读0次

    视频教程:
    C++数据类型的导出和调用(上)
    C++数据类型的导出和调用(下)
    C++数据类型的导出的补充

    函数Function

    boost::python::def()
    
    char const* greet()
    {
        return "Hello world!";
    }
    
    BOOST_PYTHON_MODULE(boost_python)
    {
        boost::python::def("greet", greet);
    }
    //python
    >>> import Python_Wrapper
    >>> Python_Wrapper.greet()
    'Hello world!'
    

    Const

    boost::python::scope().attr
    
    • boost::python::scope()用于得到当前的作用,定义新的scope对象会改变当前的作用域
    • 使用参数来构造一个新的scope对象会将关联的全局 python 对象更改为参数所持有的对象 直到作用域对象的生存期结束, 关联的全局 python 对象才会恢复到作用域对象之前的对象。
    • 官方解释和例子
    class Message
    {
    public:
        void Set(std::string msg)
        {
            m_msg = msg;
        }
        std::string Get()
        {
            return m_msg;
        }
    private:
        std::string m_msg;
    };
    
    //1.在模块中加入常量属性
    BOOST_PYTHON_MODULE(boost_python)
    {
        //const
        boost::python::scope().attr("yes") = 1;
        boost::python::scope().attr("no") = 0;
    
        boost::python::class_<Message>("Message")
            .def("Set", &Message::Set)
            .def("Get", &Message::Get); 
    }
    
    //python
    >>> import Python_Wrapper
    >>> Python_Wrapper.yes
    1
    >>> Python_Wrapper.no
    0
    ///////////////////////////////////////////////////////
    //2.改变导出顺序,也没有问题,在模块中加入常量属性
    BOOST_PYTHON_MODULE(boost_python)
    {
        boost::python::class_<Message>("Message")
            .def("Set", &Message::Set)
            .def("Get", &Message::Get); 
    
        //const
        boost::python::scope().attr("yes") = 1;
        boost::python::scope().attr("no") = 0;
    }
    
    //python
    >>> import Python_Wrapper
    >>> Python_Wrapper.yes
    1
    >>> Python_Wrapper.no
    0
    //////////////////////////////////////////////////////
    //3.如果使用boost::python::scope对象,则改变了当前的作用域,yes和no成了message类的属性
    BOOST_PYTHON_MODULE(boost_python)
    {
        //Change the current scope
        boost::python::scope newScope =  boost::python::class_<Message>("Message")
            .def("Set", &Message::Set)
            .def("Get", &Message::Get);
    
        //const Defined in the current scope(Message)
        boost::python::scope().attr("yes") = 1;
        boost::python::scope().attr("no") = 0;
    }
    
    //python
    >>> import Python_Wrapper
    >>> Python_Wrapper.yes
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: module 'Python_Wrapper' has no attribute 'yes'
    >>> Python_Wrapper.no
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: module 'Python_Wrapper' has no attribute 'no'
    >>> msg = Python_Wrapper.Message()
    >>> msg.yes
    1
    >>> msg.no
    0
    //4.使用boost::python::scope定义了新的域对象,改变了当前的作用域,这个对象出了作用域,则会恢复为之前的域对象
    BOOST_PYTHON_MODULE(Python_Wrapper)
    {
        //const
        {
        boost::python::scope newScope =  boost::python::class_<Message>("Message")
            .def("Set", &Message::Set)
            .def("Get", &Message::Get);
    
        boost::python::scope().attr("yes") = 1;
        boost::python::scope().attr("no") = 0;
        }
    
        boost::python::scope().attr("exist") = 1;
        boost::python::scope().attr("none") = 0;
    }
    //python
    >>> import Python_Wrapper
    >>> msg = Python_Wrapper.Message()
    >>> msg.yes
    1
    >>> msg.no
    0
    >>> Python_Wrapper.exist
    1
    >>> Python_Wrapper.none
    0
    

    Enum

    boost::python::enum_<T>("TName")
    
    enum MessageType
    {
        MT_START = 1,
        MT_PROCESS,
        MT_DONE,
        MT_EXCEPTION
    };
    BOOST_PYTHON_MODULE(boost_python)
    {
    //enum
        boost::python::enum_<MessageType>("MessageType")
            .value("MT_START", MT_START)
            .value("MT_PROCESS", MT_PROCESS)
            .value("MT_DONE", MT_DONE)
            .value("MT_EXCEPTION", MT_EXCEPTION);
    }
    //python
    >>> import Python_Wrapper
    >>> Python_Wrapper.MessageType.MT_START
    Python_Wrapper.MessageType.MT_START
    >>> int(Python_Wrapper.MessageType.MT_START)
    1
    >>> int(Python_Wrapper.MessageType.MT_DONE)
    3
    

    Struct

    boost::python::class_<T>("TName")
    
    struct StructionData
    {
        void hello()
        {
            std::cout << "hello, this is boost::python sample!" << std::endl;
        }
        void printmsg()
        {
            std::cout << "print message done!" << std::endl;
        }
    }
    BOOST_PYTHON_MODULE(Python_Wrapper)
    {
        //struct
        boost::python::class_<StructionData>("StructionData")
            .def("hello", &StructionData::hello)
            .def("printmsg", &StructionData::printmsg);
    }
    
    //python
    >>> import Python_Wrapper
    >>> data = Python_Wrapper.StructionData()
    >>> data.hello()
    hello, this is boost::python sample!
    >>> data.printmsg()
    print message done!
    

    Class of Default Constructor

    boost::python::class_<T>("TName")
    
    class Message
    {
    public:
        void Set(std::string msg)
        {
            m_msg = msg;
        }
        std::string Get()
        {
            return m_msg;
        }
    private:
        std::string m_msg;
    };
    
    BOOST_PYTHON_MODULE(boost_python)
    {
        //class of default constructor
            boost::python::class_<Message>("Message")
            .def("Set", &Message::Set)
            .def("Get", &Message::Get);
    }
    
    //python>>> import boost_python
    >>> import Python_Wrapper
    >>> msg = Python_Wrapper.Message()
    >>> msg.Get()
    ''
    >>> msg.Set('123')
    >>> msg.Get()
    '123'
    

    Class of Custom Constructor

    boost::python::class_<T>("TName", boost::python::init<para>())
    
    class Sum
    {
    public:
        Sum(std::string data) :m_data(data) {}
        Sum(double a, double b) :m_a(a), m_b(b) {}
    
        void Set(std::string data)
        {
            m_data = data;
        }
    
        std::string Get()
        {
            return m_data;
        }
        double Result()
        {
            return m_a + m_b;
        }
    private:
        std::string m_data;
        double m_a;
        double m_b;
    };
    
    
    BOOST_PYTHON_MODULE(boost_python)
    {
        //class of custom constructor
        boost::python::class_<Sum>("Sum", boost::python::init<std::string>())
            .def(boost::python::init<double, double>())
            .def("Set", &Sum::Set)
            .def("Get", &Sum::Get)
            .def("Result", &Sum::Result);
    }
    
    
    //python
    >>> import Python_Wrapper
    >>> s1 = Python_Wrapper.Sum()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    Boost.Python.ArgumentError: Python argument types in
        Sum.__init__(Sum)
    did not match C++ signature:
        __init__(struct _object * __ptr64, double, double)
        __init__(struct _object * __ptr64, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)
    >>> s1 = Python_Wrapper.Sum("total")
    >>> s1.Get()
    'total'
    >>> s2 = Python_Wrapper.Sum(1,2)
    >>> s2.Result()
    3.0
    

    Data member of Class

    .def_readonly()/.def_readwrite()
    
    class User
    {
    public:
        User(std::string name) :m_name(name), m_number(-1) {}
        std::string m_name;
        int m_number;
    };
    BOOST_PYTHON_MODULE(boost_python)
    {
        //data member of class
        boost::python::class_<User>("User", boost::python::init<std::string>())
            .def_readonly("name", &User::m_name)
            .def_readwrite("number", &User::m_number);
    }
    //python
    >>> import Python_Wrapper
    >>> user = Python_Wrapper.User("Jason")
    >>> user.name = "Micky"
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: can't set attribute
    >>> user.number = 12345
    >>> user.number
    12345
    

    Add Properties to Class

    .add_property()
    
    class MessagePro
    {
    public:
        void Set(std::string msg)
        {
            m_msg = msg;
        }
        std::string Get()
        {
            return m_msg;
        }
    private:
        std::string m_msg;
    };
    
    BOOST_PYTHON_MODULE(boost_python)
    {
        //add properties to class 
        boost::python::class_<MessagePro>("MessagePro")
            .add_property("info", &MessagePro::Get, &MessagePro::Set);
    }
    
    //python
    >>> import Python_Wrapper
    >>> msg = Python_Wrapper.MessagePro()
    >>> msg.set()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'MessagePro' object has no attribute 'set'
    >>> msg.get()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'MessagePro' object has no attribute 'get'
    >>> msg.info
    ''
    >>> msg.info = 'hello'
    >>> msg.info
    'hello'
    
    • 一个模块里导出的类和原始的类必须一一对应,不能导出了多个类对应一个类

    Inheritance Classes

    boost::python::class_<T, boost::python::bases<TBase>>("TName")
    
    • 必须告知导出原C++类的继承关系,不然导出后类之间就没有了继承关系
    • 告知类的继承关系关系后:
      • 继承类自动继承了基类的Python方法(即包装了的c++成员函数)
      • 即使是基类指针指向继承类对象,多态的函数也能够找到相应继承类的对应函数
    class Base
    {
    public:
        virtual ~Base() {};
        virtual std::string Name()
        {
            return "Base";
        }
    };
    
    class Derived : public Base
    {
    public:
        std::string Name()
        {
            return "Derived";
        }
    };
    
    void BaseName(Base *base)
    {
        std::cout << base->Name().c_str() << std::endl;
    }
    
    void DerivedName(Derived *derived)
    {
        std::cout << derived->Name().c_str() << std::endl;
    }
    
    Base *factory()
    {
        return new Derived();
    }
    BOOST_PYTHON_MODULE(boost_python)
    {
        //inherited
        boost::python::class_<Base>("Base", boost::python::init<>())
            .def("Name", &Base::Name);
    
        boost::python::class_<Derived, boost::python::bases<Base>>("Derived")
            .def("Name", &Derived::Name);
        boost::python::def("BaseName", BaseName);
        boost::python::def("DerivedName", DerivedName);
    
        //因为factory是生成一个新的Direved对象
        //manage_new_object告知Python生成一个指针指向一个新生成的Python对象,
        boost::python::def("factory", factory, boost::python::return_value_policy<boost::python::manage_new_object>());
    }
    //python
    >>> import Python_Wrapper
    >>> obj = Python_Wrapper.factory()
    >>> obj.Name()
    'Derived'
    >>> Python_Wrapper.BaseName(obj)
    Derived
    >>> Python_Wrapper.DerivedName(obj)
    Derived
    >>>
    >>> objBase = Python_Wrapper.Base()
    >>> objBase.Name()
    'Base'
    >>> Python_Wrapper.BaseName(objBase)
    Base
    >>> Python_Wrapper.DerivedName(objBase)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    Boost.Python.ArgumentError: Python argument types in
        Python_Wrapper.DerivedName(Base)
    did not match C++ signature:
    
    DerivedName(class Derived * __ptr64)
    

    Virtual Functions

    boost::python::wrapper
    boost::python::class_<TBase, boost::noncopyable>
    
    • 如果需要拥有虚函数的类能在导出后供Python继承,则新建一个包装类,它继承于基类并且同时继承boost::python::wrapper来对这个类进行封装,导出的时候,实际上导出的是新建的这个类
    • 包装类VFObjWrapper里对虚函数进行了规则处理,即调用是检查继承类里是否有虚函数的重写,如果没有,调用基类的虚函数(因为基类的虚函数有实现)
    class VFObj
    {
    public:
        virtual ~VFObj() {};
        virtual int Func() { return 0; }
    };
    
    class VFObjWrapper : public VFObj, public boost::python::wrapper<VFObj>
    {
    public:
        int Func()
        {
            if (boost::python::override Func = this->get_override("Func"))
            {
                return Func();
            }
            return VFObj::Func();
        }
        int default_Func()
        {
            return this->VFObj::Func();
        }
    };
    BOOST_PYTHON_MODULE(boost_python)
    {
        //virtual function
        boost::python::class_<VFObjWrapper, boost::noncopyable>("VFObj")
            .def("Func", &VFObj::Func, &VFObjWrapper::Func);
    }
    
    //python
    >>> import Python_Wrapper
    >>> objVF = Python_Wrapper.VFObj()
    >>> objVF.Func()
    0
    //新的继承类重写了Func函数
    >>> class newObj(Python_Wrapper.VFObj):
    ...     def Func(self):
    ...             return 88
    ...
    >>> obj = newObj()
    >>> obj.Func()
    88
    //新的继承类没有重现Func函数,调用Func函数会调用基类的Func函数
    >>> class derivedObj(Python_Wrapper.VFObj):
    ...     def newFunc():
    ...             pass
    ...
    >>> dObj = derivedObj()
    >>> dObj.Func()
    0
    

    Pure Virtual Functions

    boost::python::wrapper
    boost::python::class_<TBase, boost::noncopyable>
    boost::python::pure_virtual
    
    • 如果需要****拥有****纯虚函数的类能在导出后供Python继承,则****新建一个包装类,它继承于基类并且同时继承boost::python::wrapper来对这个类进行封装,导出的时候,实际上导出的是新建的这个类
    • 包装类PVFObjWrapper里对纯虚函数进行了规则处理,即调用的是继承类的虚函数
    • 导出是使用boost::python::pure_virtual告知哪个是纯虚函数。
    class PVFObj
    {
    public:
        virtual ~PVFObj() {}
        virtual int Func() = 0;
    };
    
    class PVFObjWrapper : public PVFObj, public boost::python::wrapper<PVFObj>
    {
    public:
        int Func()
        {
            return this->get_override("Func")();
        }
    };
    
    
    
    BOOST_PYTHON_MODULE(boost_python)
    {
        //pure virtual function
        boost::python::class_<PVFObjWrapper, boost::noncopyable>("PVFObj")
            .def("Func", boost::python::pure_virtual(&PVFObj::Func));
    }
    //python
    >>> import Python_Wrapper
    >>> obj = Python_Wrapper.PVFObj()
    >>> obj.Func()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    RuntimeError: Pure virtual function called
    >>> class derivedObj(Python_Wrapper.PVFObj):
    ...     def Func(self):
    ...             return 88
    ...
    >>> dObj = derivedObj()
    >>> dObj.Func()
    88
    

    Operators and Special Functions of Class

    .def(boost::python::self + boost::python::self);
    
    class Operand
    {
    public:
        Operand() :m_num(0) {}
        Operand(int num) :m_num(num) {}
    
        int num()
        {
            return m_num;
        }
        Operand& operator+(const Operand& other)
        {
            m_num += other.m_num;
            return *this;
        }
        Operand& operator+(int num)
        {
            m_num += num;
            return *this;
        }
        Operand& operator-(const Operand& other)
        {
            m_num -= other.m_num;
            return *this;
        }
        Operand& operator-(int num)
        {
            m_num -= num;
            return *this;
        }
        Operand& operator+=(const Operand& other)
        {
            return operator+(other);
        }
    
        Operand& operator+=(int num)
        {
            return operator+(num);
        }
        Operand& operator-=(const Operand& other)
        {
            return operator-(other);
        }
        Operand& operator-=(int num)
        {
            return operator-(num);
        }
        bool operator<(const Operand& other)
        {
            return (m_num < other.m_num);
        }
        int abs()
        {
            m_num = std::abs(m_num);
            return m_num;
        }
    private:
        int m_num;
    };
    
    std::ostream& operator<<(std::ostream& out, Operand opr)
    {
        out << opr.num();
        return out;
    }
    BOOST_PYTHON_MODULE(boost_python)
    {
        //operator
        boost::python::class_<Operand>("Operand", boost::python::init<>())
            .def(boost::python::init<int>())
            .def("num", &Operand::num)
            .def(boost::python::self + boost::python::self)
            .def(boost::python::self + int())
            .def(boost::python::self - boost::python::self)
            .def(boost::python::self - int())
            .def(boost::python::self += boost::python::self)
            .def(boost::python::self += int())
            .def(boost::python::self -= boost::python::self)
            .def(boost::python::self -= int())
            .def(boost::python::self < boost::python::self)
            .def("abs", &Operand::abs)
            .def(str(boost::python::self));
    }
    
    //python
    >>> import Python_Wrapper
    >>> opr1 = Python_Wrapper.Operand(10)
    >>> opr1.num()
    10
    >>> opr1 + 50
    <Python_Wrapper.Operand object at 0x000002639BD5A9E0>
    >>> opr1.num()
    60
    >>> opr2 = Python_Wrapper.Operand(30)
    >>> opr2.num()
    30
    >>> opr1 - opr2
    <Python_Wrapper.Operand object at 0x000002639BD5A9E0>
    >>> opr1.num()
    30
    >>> opr1 -= opr2
    >>> opr1.num()
    0
    >>> opr1 - 20
    <Python_Wrapper.Operand object at 0x000002639BD5A9E0>
    >>> opr1.num()
    -20
    >>> opr1 < opr2
    True
    >>> str(opr2)
    '30'
    

    Function Overloading

    • 需要重载声明
    class Calculator
    {
    public:
    
        int Func(int a)
        {
            return a;
        }
    
        int Func(int a, int b)
        {
            return a + b;
        }
    
        int Func(int a, int b, int c)
        {
            return a + b - c;
        }
    };
    
    //重载声明
    int(Calculator::*Func1)(int) = &Calculator::Func;
    int(Calculator::*Func2)(int, int) = &Calculator::Func;
    int(Calculator::*Func3)(int, int, int) = &Calculator::Func;
    BOOST_PYTHON_MODULE(boost_python)
    {
        //function overload of class
        boost::python::class_<Calculator>("Calculator", boost::python::init<>())
            .def("Func", Func1)
            .def("Func", Func2)
            .def("Func", Func3);
    }
    
    //python
    >>> import Python_Wrapper
    >>> calc = Python_Wrapper.Calculator()
    >>> calc.Func(3)
    3
    >>> calc.Func(3, 4)
    7
    >>> calc.Func(3, 4, 10)
    -3
    >>> calc.Func(3, 4, 10, 15)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    Boost.Python.ArgumentError: Python argument types in
        Calculator.Func(Calculator, int, int, int, int)
    did not match C++ signature:
        Func(class Calculator {lvalue}, int, int, int)
        Func(class Calculator {lvalue}, int, int)
        Func(class Calculator {lvalue}, int)
    

    Function's Default Parameters of Class

    boost::python::optional //构造函数的可选参数标识
    BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS //定义导出函数名,最少参数和最多参数
    
    class CalculatorPro
    {
    public:
        CalculatorPro()
        {
            m_value = 0.0;
        }
    
        CalculatorPro(int a, double b = 2.0, int c = 10)
        {
            m_value = a + b + c;
        }
        double Func(int a, double b = 3.0, int c = 5)
        {
            return a + b - c;
        }
        double Value()
        {
            return m_value;
        }
    
    private:
        double m_value;
    };
    
    
    //1为最少参数,3为最多参数
    BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(CalculatorPro_overloads, Func, 1, 3);
    
    BOOST_PYTHON_MODULE(boost_python)
    {
        //function's default parameters of class
        boost::python::class_<CalculatorPro>("CalculatorPro", boost::python::init<>())
            .def(boost::python::init<int, boost::python::optional<double, int>>())
            .def("Func", &CalculatorPro::Func, CalculatorPro_overloads())
            .def("Value", &CalculatorPro::Value);
    
    }
    
    //python
    >>> import Python_Wrapper
    >>> calc = Python_Wrapper.CalculatorPro()
    >>> calc.Value()
    0.0
    >>> calc1 = Python_Wrapper.CalculatorPro(10)
    >>> calc1.Value()
    22.0
    >>> calc2 = Python_Wrapper.CalculatorPro(10, 30)
    >>> calc2.Value()
    50.0
    >>> calc3 = Python_Wrapper.CalculatorPro(10, 30, 50)
    >>> calc3.Value()
    90.0
    >>> calc4 = Python_Wrapper.CalculatorPro(10, 30, 50, 60)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    Boost.Python.ArgumentError: Python argument types in
        CalculatorPro.__init__(CalculatorPro, int, int, int, int)
    did not match C++ signature:
        __init__(struct _object * __ptr64, int)
        __init__(struct _object * __ptr64, int, double)
        __init__(struct _object * __ptr64, int, double, int)
        __init__(struct _object * __ptr64)
    >>>
    >>> calc5 = Python_Wrapper.CalculatorPro()
    >>> calc5.Func(10)
    8.0
    >>> calc5.Func(10, 2.0)
    7.0
    >>> calc5.Func(10, 2.0, 30)
    -18.0
    >>> calc5.Func(10, 2.0, 30, 40)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    Boost.Python.ArgumentError: Python argument types in
        CalculatorPro.Func(CalculatorPro, int, float, int, int)
    did not match C++ signature:
        Func(class CalculatorPro {lvalue}, int)
        Func(class CalculatorPro {lvalue}, int, double)
        Func(class CalculatorPro {lvalue}, int, double, int)
    

    Function's Default Parameters

    BOOST_PYTHON_FUNCTION_OVERLOADS //定义导出函数名,最少参数和最多参数
    
    double FuncofDefaultParas(int a, double b = 2.0, double c = 3.0)
    {
        return a + b + c;
    }
    BOOST_PYTHON_FUNCTION_OVERLOADS(FuncofDefaultParas_overload, FuncofDefaultParas, 1, 3);
    
    BOOST_PYTHON_MODULE(boost_python)
    {
        //function's default parameters
        boost::python::def("FuncofDefaultParas", FuncofDefaultParas, FuncofDefaultParas_overload());
    }
    >>> import Python_Wrapper
    >>> Func = Python_Wrapper.FuncofDefaultParas
    >>> Func
    <Boost.Python.function object at 0x000001E7F20511C0>
    >>> Func(1)
    6.0
    >>> Func(1, 5)
    9.0
    >>> Func(1, 5, 10)
    16.0
    >>> Func(2, 5, 10, 3)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    Boost.Python.ArgumentError: Python argument types in
        Python_Wrapper.FuncofDefaultParas(int, int, int, int)
    did not match C++ signature:
        FuncofDefaultParas(int)
        FuncofDefaultParas(int, double)
        FuncofDefaultParas(int, double, double)
    

    Smart Pointer

    boost::python::register_ptr_to_python<TP>()
    
    class Data
    {
    public:
        void Set(int data)
        {
            m_data = data;
        }
        int Get()
        {
            return m_data;
        }
    private:
        int m_data;
    };
    
    //smart pointer defined
    using DataPtr = std::shared_ptr<Data>;
    
    //smart pointer object
    DataPtr pData(new Data);
    
    BOOST_PYTHON_MODULE(boost_python)
    {
        //smart point;
        boost::python::class_<Data>("Data", boost::python::init<>())
            .def("Set", &Data::Set)
            .def("Get", &Data::Get);
        boost::python::register_ptr_to_python<DataPtr>();
        boost::python::scope().attr("pData") = pData;
    }
    
    //python
    >>> import Python_Wrapper
    >>> Python_Wrapper.pData.Get()
    -842150451
    >>> Python_Wrapper.pData.Set(12345)
    >>> Python_Wrapper.pData.Get()
    12345
    
    • 不加入boost::python::register_ptr_to_python描述导出智能指针,导入module时会报错
    BOOST_PYTHON_MODULE(boost_python)
    {
        //smart point;
        boost::python::class_<Data>("Data", boost::python::init<>())
            .def("Set", &Data::Set)
            .def("Get", &Data::Get);
    
        //boost::python::register_ptr_to_python<DataPtr>();
        boost::python::scope().attr("pData") = pData
    }
    //import
    >>> import Python_Wrapper
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    SystemError: initialization of Python_Wrapper raised unreported exception
    >>>
    
    • 只导出智能指针,不导出智能指针指向的类,也会报错
    BOOST_PYTHON_MODULE(boost_python)
    {
        //smart point;
        /*
        boost::python::class_<Data>("Data", boost::python::init<>())
            .def("Set", &Data::Set)
            .def("Get", &Data::Get);
            */
    
        boost::python::register_ptr_to_python<DataPtr>();
    
    
        boost::python::scope().attr("pData") = pData
      }
      
    //python
    >>> import Python_Wrapper
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    SystemError: initialization of Python_Wrapper raised unreported exception
    

    函数返回值为引用的导出

    • boost::python::return_value_policy<boost::python::reference_existing_object>()
    • 本例也可以使用boost::python::return_internal_reference<>()
    class A
    {
    public:
        int value;
    };
    class B
    {
    public:
        A a;
    };
    A& getA(B &b)
    {
        return b.a;
    }
    BOOST_PYTHON_MODULE(boost_python)
    {
       boost::python::class_<A>("A", boost::python::init<>())
            .def_readwrite("value", &A::value);
        boost::python::class_<B>("B", boost::python::init<>())
            .def_readwrite("a", &B::a);
        boost::python::def("getA", getA, boost::python::return_value_policy<boost::python::reference_existing_object>());
        //boost::python::def("getA", getA, boost::python::return_internal_reference<1>());
    }
    //python
    >>> import Python_Wrapper
    >>> bObj = Python_Wrapper.B()
    >>> aObj = Python_Wrapper.getA(bObj)
    >>> aObj.value
    0
    >>> bObj.a.value = 10
    >>> aObj.value
    10
    >>> aObj.value = 20
    >>> bObj.a.value
    20
    //aObj指向和bObj的a时同一个对象
    

    函数返回值为静态对象的导出

    boost::python::return_value_policy<boost::python::reference_existing_object>()

    class D
    {
    public:
        int value;
    };
    
    D& getStaticD()
    {
        static D d;
        d.value = 10;
        return d;
    }
    BOOST_PYTHON_MODULE(boost_python)
    {
        boost::python::class_<D>("D", boost::python::init<>())
            .def_readwrite("value", &D::value);
        
        boost::python::def("getD", getStaticD, boost::python::return_value_policy<boost::python::reference_existing_object>());
    }
    >>> import Python_Wrapper
    >>> dObj =  Python_Wrapper.getD()
    >>> dObj.value
    10
    >>> dObj.value = 20
    >>> dObj.value
    20
    

    函数返回值为新对象的导出

    • boost::python::return_value_policy<boost::python::manage_new_object>()
    class C
    {
    public:
        int value;
    };
    C* getC()
    {
        return new C();
    }
    
    BOOST_PYTHON_MODULE(boost_python)
    {
           boost::python::class_<C>("C", boost::python::init<>())
            .def_readwrite("value", &C::value);
        boost::python::def("getC", getC, boost::python::return_value_policy<boost::python::manage_new_object>());
    }
    //python
    >>> import Python_Wrapper
    >>> cObj = Python_Wrapper.getC()
    >>> cObj.value = 10
    >>> cObj.value
    10
    

    模块导出的类必须一一对应

    一个模块里导出的类和原始的类必须一一对应,不能导出了多个类对应一个类

    class E
    {
    public:
        int value;
    };
    
    BOOST_PYTHON_MODULE(boost_python)
    {
        boost::python::class_<E>("E", boost::python::init<>())
            .def_readwrite("value", &E::value);
        boost::python::class_<E>("EClone", boost::python::init<>())
            .def_readwrite("value", &E::value);
    }
    //python
    >>> import Python_Wrapper
    

    相关文章

      网友评论

          本文标题:C++和Python的混合编程-C++数据类型的导出和调用

          本文链接:https://www.haomeiwen.com/subject/nneceqtx.html