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

2019-02-11  本文已影响0人  JasonLiThirty

视频教程:
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
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")
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>
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
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_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

函数返回值为引用的导出

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

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

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
上一篇下一篇

猜你喜欢

热点阅读