C++和Python的混合編程-C++數(shù)據(jù)類型的導(dǎo)出和調(diào)用

視頻教程:
C++數(shù)據(jù)類型的導(dǎo)出和調(diào)用(上)
C++數(shù)據(jù)類型的導(dǎo)出和調(diào)用(下)
C++數(shù)據(jù)類型的導(dǎo)出的補(bǔ)充

函數(shù)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()用于得到當(dāng)前的作用,定義新的scope對象會(huì)改變當(dāng)前的作用域
  • 使用參數(shù)來構(gòu)造一個(gè)新的scope對象會(huì)將關(guān)聯(lián)的全局 python 對象更改為參數(shù)所持有的對象 直到作用域?qū)ο蟮纳嫫诮Y(jié)束, 關(guān)聯(lián)的全局 python 對象才會(huì)恢復(fù)到作用域?qū)ο笾暗膶ο蟆?/li>
  • 官方解釋和例子
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.改變導(dǎo)出順序,也沒有問題,在模塊中加入常量屬性
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對象,則改變了當(dāng)前的作用域戒幔,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定義了新的域?qū)ο螅淖兞水?dāng)前的作用域诗茎,這個(gè)對象出了作用域,則會(huì)恢復(fù)為之前的域?qū)ο?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'
  • 一個(gè)模塊里導(dǎo)出的類和原始的類必須一一對應(yīng)献汗,不能導(dǎo)出了多個(gè)類對應(yīng)一個(gè)類

Inheritance Classes

boost::python::class_<T, boost::python::bases<TBase>>("TName")
  • 必須告知導(dǎo)出原C++類的繼承關(guān)系敢订,不然導(dǎo)出后類之間就沒有了繼承關(guān)系
  • 告知類的繼承關(guān)系關(guān)系后:
    • 繼承類自動(dòng)繼承了基類的Python方法(即包裝了的c++成員函數(shù))
    • 即使是基類指針指向繼承類對象,多態(tài)的函數(shù)也能夠找到相應(yīng)繼承類的對應(yīng)函數(shù)
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);

    //因?yàn)閒actory是生成一個(gè)新的Direved對象
    //manage_new_object告知Python生成一個(gè)指針指向一個(gè)新生成的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>
  • 如果需要擁有虛函數(shù)的類能在導(dǎo)出后供Python繼承楚午,則新建一個(gè)包裝類,它繼承于基類并且同時(shí)繼承boost::python::wrapper來對這個(gè)類進(jìn)行封裝尿招,導(dǎo)出的時(shí)候矾柜,實(shí)際上導(dǎo)出的是新建的這個(gè)類
  • 包裝類VFObjWrapper里對虛函數(shù)進(jìn)行了規(guī)則處理,即調(diào)用是檢查繼承類里是否有虛函數(shù)的重寫就谜,如果沒有怪蔑,調(diào)用基類的虛函數(shù)(因?yàn)榛惖奶摵瘮?shù)有實(shí)現(xiàn))
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函數(shù)
>>> class newObj(Python_Wrapper.VFObj):
...     def Func(self):
...             return 88
...
>>> obj = newObj()
>>> obj.Func()
88
//新的繼承類沒有重現(xiàn)Func函數(shù),調(diào)用Func函數(shù)會(huì)調(diào)用基類的Func函數(shù)
>>> 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
  • 如果需要****擁有****純虛函數(shù)的類能在導(dǎo)出后供Python繼承丧荐,則****新建一個(gè)包裝類饮睬,它繼承于基類并且同時(shí)繼承boost::python::wrapper來對這個(gè)類進(jìn)行封裝,導(dǎo)出的時(shí)候篮奄,實(shí)際上導(dǎo)出的是新建的這個(gè)類
  • 包裝類PVFObjWrapper里對純虛函數(shù)進(jìn)行了規(guī)則處理捆愁,即調(diào)用的是繼承類的虛函數(shù)
  • 導(dǎo)出是使用boost::python::pure_virtual告知哪個(gè)是純虛函數(shù)。
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 //構(gòu)造函數(shù)的可選參數(shù)標(biāo)識
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS //定義導(dǎo)出函數(shù)名窟却,最少參數(shù)和最多參數(shù)
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為最少參數(shù)昼丑,3為最多參數(shù)
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 //定義導(dǎo)出函數(shù)名,最少參數(shù)和最多參數(shù)
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描述導(dǎo)出智能指針夸赫,導(dǎo)入module時(shí)會(huì)報(bào)錯(cuò)
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
>>>
  • 只導(dǎo)出智能指針菩帝,不導(dǎo)出智能指針指向的類,也會(huì)報(bào)錯(cuò)
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

函數(shù)返回值為引用的導(dǎo)出

  • 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時(shí)同一個(gè)對象

函數(shù)返回值為靜態(tài)對象的導(dǎo)出

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

函數(shù)返回值為新對象的導(dǎo)出

  • 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

模塊導(dǎo)出的類必須一一對應(yīng)

一個(gè)模塊里導(dǎo)出的類和原始的類必須一一對應(yīng)茬腿,不能導(dǎo)出了多個(gè)類對應(yīng)一個(gè)類

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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呼奢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子切平,更是在濱河造成了極大的恐慌握础,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悴品,死亡現(xiàn)場離奇詭異禀综,居然都是意外死亡简烘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門定枷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來孤澎,“玉大人,你說我怎么就攤上這事欠窒「残瘢” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵岖妄,是天一觀的道長姐扮。 經(jīng)常有香客問我,道長衣吠,這世上最難降的妖魔是什么茶敏? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮缚俏,結(jié)果婚禮上惊搏,老公的妹妹穿的比我還像新娘。我一直安慰自己忧换,他們只是感情好恬惯,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著亚茬,像睡著了一般酪耳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刹缝,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天碗暗,我揣著相機(jī)與錄音,去河邊找鬼梢夯。 笑死言疗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的颂砸。 我是一名探鬼主播噪奄,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼人乓!你這毒婦竟也來了勤篮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤色罚,失蹤者是張志新(化名)和其女友劉穎碰缔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體保屯,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡手负,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了姑尺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片竟终。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖切蟋,靈堂內(nèi)的尸體忽然破棺而出统捶,到底是詐尸還是另有隱情,我是刑警寧澤柄粹,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布喘鸟,位于F島的核電站,受9級特大地震影響驻右,放射性物質(zhì)發(fā)生泄漏什黑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一堪夭、第九天 我趴在偏房一處隱蔽的房頂上張望愕把。 院中可真熱鬧,春花似錦森爽、人聲如沸恨豁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽橘蜜。三九已至,卻和暖如春付呕,著一層夾襖步出監(jiān)牢的瞬間计福,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工徽职, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棒搜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓活箕,卻偏偏與公主長得像力麸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子育韩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容