ubuntu下用boost python進行c++ python3混合編程

參考

https://www.jianshu.com/p/bc0f18b60c89

 

人果然是健忘的,幾年前用過這個,轉眼就忘記了。再次拾起來,記錄下。

忘記了去掉lib**.so的lib.

sudo apt-get install libboost-python-dev 

bot_curve.cpp

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <boost/python.hpp>
#include<iostream>
#include<stdio.h>
using namespace boost::python;
#include <cmath>
class circle_2d {
  // circle center(a,b); radius r; time t
  // x = a+r*cost;
  // y= b+r*sint
public:
  float a, b, r;
  float dist_delt;
  bool clockwise;

public:
  circle_2d(float ma, float mb, float mr = 10): a(ma),b(mb),r(mr)
  {
	  printf("construct circle_2d\n");
  }

  // x,y input curent position
  // and output next position x y
  float next(float x, float y){
	  printf("next radius=%f\n",r);
	  return x+y;
  }
};


BOOST_PYTHON_MODULE(botcurve) {
  // const
  // boost::python::scope().attr("yes") = 1;
  // boost::python::scope().attr("no") = 0;

  boost::python::class_<circle_2d>(
      "circle_2d", boost::python::init<float, float, float>())
      .def("next", &circle_2d::next);
 
}

CMakeLists.txt

如果要編譯python2的包,在CMakeLists.txt中添加如下兩行

set(PYTHON_INCLUDE_DIR "/usr/include/python2.7")

set(PYTHON_LIBRARY "/usr/lib/x86_64-linux-gnu/libpython2.7.so" )

可能遇到

ImportError: /usr/lib/x86_64-linux-gnu/libboost_python-py35.so.1.58.0: undefined symbol: PyUnicode_AsUTF8String

ImportError: /home/zhangym/luhabo/src/botutils/build/botcurve.so: undefined symbol: _ZN5boost6python6detail11init_moduleEPKcPFvvE
 

錯誤解決:
$ sudo  rm /usr/lib/x86_64-linux-gnu/libboost_python.so

$ sudo ln -s /usr/lib/x86_64-linux-gnu/libboost_python-py27.so /usr/lib/x86_64-linux-gnu/libboost_python.so

 


cmake_minimum_required(VERSION 3.2)

PROJECT(botcurve)

SET(CMAKE_CXX_FLAGS "-std=c++0x")
SET (PROJECT_ROOT "${PROJECT_SOURCE_DIR}")
SET (PROJECT_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/inc")
SET (PROJECT_SOURCE_DIR "${PROJECT_SOURCE_DIR}/src")

find_package(Boost COMPONENTS filesystem system date_time thread python REQUIRED)
message("Include dirs of boost: " ${Boost_INCLUDE_DIRS} )
message("Libs of boost: " ${Boost_LIBRARIES} )

find_package(PythonLibs REQUIRED)
message("Include dirs of Python: " ${PYTHON_INCLUDE_DIRS} )
message("Libs of Python: " ${PYTHON_LIBRARIES} )


INCLUDE_DIRECTORIES(
${PROJECT_INCLUDE_DIR}
${Boost_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
)

link_directories(${Boost_LIBRARY_DIRS})
link_directories(${PYTHON_LIBRARIES})

SET(SRC
     src/bot_curve.cpp
)

add_library(botcurve SHARED ${SRC}) 

target_link_libraries(botcurve
${Boost_LIBRARIES}
${PYTHON_LIBRARIES}
)

$mv libbotcurve.so botcurve.so 

遇到錯誤:

ImportError: /usr/lib/x86_64-linux-gnu/libboost_python-py27.so.1.58.0: undefined symbol: PyClass_Type

錯誤解決:
$ sudo rm /usr/lib/x86_64-linux-gnu/libboost_python.so

$ sudo ln -s /usr/lib/x86_64-linux-gnu/libboost_python-py35.so /usr/lib/x86_64-linux-gnu/libboost_python.so

 

 

--------轉自

Boost::python實現C++和Python的混合編程(導出和調用)

 

JasonLiThirty已關注

0.0972019.02.11 22:12:32字數 868閱讀 2,349

以下是各種基本類型導出的格式和關鍵字


Function

boost::python::def()
char const* greet()
{
    return "Hello world!";
}

BOOST_PYTHON_MODULE(boost_python)
{
    boost::python::def("greet", greet);
}

//python
>>> import boost_python
>>> boost_python.greet()
'Hello world!'

Const

boost::python::scope().attr
  • boost::python::scope()用於得到當前的作用域,需要注意的恰恰就是當前作用域
  • 定義新的scope對象會改變當前的作用域
class Message
{
public:
    void set(std::string msg)
    {
        this->msg = msg;
    }

    std::string get()
    {
        return this->msg;
    }

private:
    std::string 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 boost_python
>>> boost_python.yes
1
>>> boost_python.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 boost_python
>>> boost_python.yes
1
>>> boost_python
0

//////////////////////////////////////////////////////
//3.如果使用boost::python::scope對象,則改變了當前的作用域,yes和no成了message類的屬性
BOOST_PYTHON_MODULE(boost_python)
{
    //Change the current scope
    boost::python::scope scopechange = 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 boost_python
>>> boost_python.yes
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'yes'
>>> boost_python.no
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'no'
>>> msg = boost_python.Message()
>>> msg.yes
1
>>> msg.no
0
>>>
  • 官方解釋和例子
  • The scope class has an associated global Python object which controls the Python namespace in which new extension classes and wrapped functions will be defined as attributes. //作用域類具有關聯的全局 python 對象, 該對象控制 python 命名空間, 在該命名空間中, 新的擴展類和包裝的函數將被定義爲屬性。
  • Default-constructing a new scope object binds it to the associated global Python object. Constructing a scope object with an argument changes the associated global Python object to the one held by the argument, until the lifetime of the scope object ends, at which time the associated global Python object reverts to what it was before the scope object was constructed.//使用參數來構造一個新的scope對象會將關聯的全局 python 對象更改爲參數所持有的對象 直到作用域對象的生存期結束, 關聯的全局 python 對象纔會恢復到作用域對象之前的對象。
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/scope.hpp>
using namespace boost::python;

struct X
{
  void f() {}

  struct Y { int g() { return 42; } };
};

BOOST_PYTHON_MODULE(nested)
{
   // add some constants to the current (module) scope
   scope().attr("yes") = 1;
   scope().attr("no") = 0;

   // Change the current scope 
   scope outer
       = class_<X>("X")
            .def("f", &X::f)
            ;

   // Define a class Y in the current scope, X
   class_<X::Y>("Y")
      .def("g", &X::Y::g)
      ;
}

//python
>>> import nested
>>> nested.yes
1
>>> y = nested.X.Y()
>>> y.g()
421

Class of Default Constructor

boost::python::class_<T>("TName")
class Message
{
public:
    void set(std::string msg)
    {
        this->msg = msg;
    }

    std::string get()
    {
        return this->msg;
    }

private:
    std::string msg;
};

BOOST_PYTHON_MODULE(boost_python)
{
    //class of default constructor
    boost::python::class_<Message>("Message")
        .def("set", &Message::set)
        .def("get", &Message::get); 
        //.def("print", &Message::get); //不可以使用print這種關鍵字作爲導出函數名
}

//python>>> import boost_python
>>> msg=boost_python.Message()
>>> msg.get()
''
>>> msg.set("hello")
>>> msg.get()
'hello'

Class of Custom Constructor

boost::python::class_<T>("TName", boost::python::init<para>())
class Sum
{
public:
    Sum(std::string msg): m_msg(msg) {}
    Sum(double a, double b) : m_a(a), m_b(b) {}
    void set(std::string msg)
    {
        this->m_msg = msg;
    }
    std::string get()
    {
        return this->m_msg;
    }
    double result()
    {
        return m_a + m_b;
    }

private:
    std::string m_msg;
    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>()) //default constructor
        .def(boost::python::init<double, double>()) //custom constructor
        .def("set", &Sum::set)
        .def("get", &Sum::get)
        .def("result", &Sum::result);
}


//python
>>> import boost_python
>>> s = boost_python.Sum() //Error
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> >)
>>> s = boost_python.Sum("hello")
>>> s.get()
'hello'

>>> sum = boost_python.Sum(3,4)
>>> sum.result()
7.0

Data member of Class

.def_readonly()/.def_readwrite()
class Var
{
public:
    Var(std::string name) :m_name(name), m_value() {}
    std::string m_name;
    float m_value;
};

BOOST_PYTHON_MODULE(boost_python)
{
    //data member of class
    boost::python::class_<Var>("Var", boost::python::init<std::string>())
        .def_readonly("name", &Var::m_name)
        .def_readwrite("value", &Var::m_value);
}

//python
>>> import boost_python
>>> v = boost_python.Var("Micky")
>>> v.name
'Micky'

>>> v.name = "hello" //Error
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> v.value = "hello" //Error
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    None.None(Var, str)
did not match C++ signature:
    None(class Var {lvalue}, float)
>>> v.value = 123
>>> v.value
## 123.0

Add Properties to Class

.add_property()
class NewMessage
{
public:
    void set(std::string msg)
    {
        this->msg = msg;
    }

    std::string get()
    {
        return this->msg;
    }

private:
    std::string msg;
};


BOOST_PYTHON_MODULE(boost_python)
{
    //add properties to class 
    boost::python::class_<NewMessage>("NewMessage", boost::python::init<>()) 
        .add_property("msg", &NewMessage::get, &NewMessage::set);
}


//python
>>> import boost_python
>>> newMsg = boost_python.NewMessage()
>>> newMsg.get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NewMessage' object has no attribute 'get'
>>> newMsg.msg
''
>>> newMsg.msg = "hello"
>>> newMsg.msg
'hello'

Inheritance Classes

boost::python::class_<T, boost::python::bases<TBase>>("TName")
  • 必須告知導出原C++類的繼承關係,不然導出後類之間就沒有了繼承關係
  • 告知類的繼承關係關係後:
    • 繼承類自動繼承了基類的Python方法(即包裝了的c++成員函數)
    • 即使是基類指針指向繼承類對象,多態的函數也能夠找到相應繼承類的對應函數
class Base
{
public:
    virtual ~Base() {}
    virtual std::string getName()
    {
        return "Base";
    }
};

class Derived : public Base
{
public:
    std::string getName()
    {
        return "Derived";
    }
};

void BaseName(Base *base)
{
    std::cout << base->getName().c_str() << std::endl;
}

void DerivedName(Derived *derived)
{
    std::cout << derived->getName().c_str() << std::endl;
}

Base *factory()
{
    return new Derived;
}

BOOST_PYTHON_MODULE(boost_python)
{
    //inherited
    boost::python::class_<Base>("Base", boost::python::init<>())
        .def("getName", &Base::getName);
    boost::python::class_<Derived, boost::python::bases<Base>>("Derived", boost::python::init<>())
        .def("getName", &Derived::getName);

    boost::python::def("BaseName", BaseName);
    boost::python::def("DerivedName", DerivedName);
    //因爲factory是生成一個新的Direved對象
    //manage_new_object告知Python生成一個指針指向一個新的Base的Python對象,直到這個對象被銷燬
    boost::python::def("factory", factory, boost::python::return_value_policy<boost::python::manage_new_object>());
}

//python
>>> >>> import boost_python
>>> d = boost_python.factory()
>>> boost_python.BaseName(d)
Derived
>>> boost_python.DerivedName(d)
Derived
>>> d.getName()
'Derived'

>>> b = boost_python.Base()
>>> boost_python.BaseName(b)
Base
>>> boost_python.DerivedName(b) //Error
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    boost_python.DerivedName(Base)
did not match C++ signature:
    DerivedName(class Derived * __ptr64)
>>> b.getName()
'Base'

Pure Virtual Functions & Virtual Functions

boost::python::wrapper
boost::python::class_<TBase, boost::noncopyable>
boost::python::pure_virtual
  • 如果需要純虛函數和虛函數的類能在導出後供Python繼承,則****新建一個包裝類,它繼承於基類並且同時繼承boost::python::wrapper來對這個類進行封裝,導出的時候,實際上導出的是新建的這個類
  • 純虛函數
    • 包裝類BasePVFWrap裏對純虛函數進行了規則處理,即調用的是繼承類的虛函數
    • 導出是使用boost::python::pure_virtual告知哪個是純虛函數。
class BasePVF
{
public:
    virtual ~BasePVF() {}
    virtual int f() = 0;
};

class BasePVFWrap : public BasePVF, public boost::python::wrapper<BasePVF>
{
public:
    int f()
    {
        return this->get_override("f")();
    }
};

BOOST_PYTHON_MODULE(boost_python)
{
    //pure virtual function
    boost::python::class_<BaseVFWrap, boost::noncopyable>("BaseVF")
        .def("f", &BaseVF::f, &BaseVFWrap::default_f);
}

//python
>>> import boost_python
>>> object_pvf = boost_python.BasePVF()
>>> object_pvf.f() //Error, Pure virtual function called
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: Pure virtual function called
>>> class DerivedPVF(boost_python.BasePVF):
...     def f(self):
...             return 50
...
>>> object_derived_pvf = DerivedPVF()
>>> object_derived_pvf.f()
50
  • 虛函數
    • 包裝類BaseVFWrap裏對虛函數進行了規則處理,即調用是檢查繼承類裏是否有虛函數的重寫,如果沒有,調用基類的虛函數(因爲基類的虛函數有實現)
    • 導出時,使得f屬性關聯兩個函數,如果沒有規則處理函數f,則調用基類的虛函數
class BaseVF
{
public:
    virtual ~BaseVF() {}
    virtual int f() { return 0; }
};

class BaseVFWrap : public BaseVF, public boost::python::wrapper<BaseVF>
{
public:
    int f()
    {
        if (boost::python::override f = this->get_override("f"))
        {
            return f();
        }
        return BaseVF::f();
    }

    int default_f() {
        return this->BaseVF::f();
    }
};

BOOST_PYTHON_MODULE(boost_python)
{
    //virtual function
    boost::python::class_<BasePVFWrap, boost::noncopyable>("BasePVF")
        .def("f", boost::python::pure_virtual(&BasePVF::f));
}


//python
>>> object_fv = boost_python.BaseVF()
>>> object_fv.f()
0
>>> class DerivedVF(boost_python.BaseVF):
...     def f(self):
...             return 100
...
>>> object_derived_vf = DerivedVF()
>>> object_derived_vf.f()
100

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 get()
    {
        return this->m_num;
    }
    Operand& operator+(const Operand& other);
    Operand& operator+(int num);
    Operand& operator-(const Operand& other);
    Operand& operator-(int num);
    Operand& operator+=(const Operand& other);
    Operand& operator+=(int num);
    Operand& operator-=(const Operand& other);
    Operand& operator-=(int num);
    bool operator<(const Operand& other);

    int abs();

private:
    int m_num;
};

Operand& Operand::operator+(const Operand& other)
{
    m_num += other.m_num;
    return *this;
}

Operand& Operand::operator+(int num)
{
    m_num += num;
    return *this;
}

Operand& Operand::operator-(const Operand& other)
{
    m_num -= other.m_num;
    return *this;
}

Operand& Operand::operator-(int num)
{
    m_num -= num;
    return *this;
}

Operand& Operand::operator+=(const Operand& other)
{
    return operator+(other);
}

Operand& Operand::operator+=(int num)
{
    return operator+(num);
}

Operand& Operand::operator-=(const Operand& other)
{
    return operator-(other);
}

Operand& Operand::operator-=(int num)
{
    return operator-(num);
}

bool Operand::operator<(const Operand& other)
{
    if (m_num < other.m_num)
    {
        return true;
    }
    return false;
}

int Operand::abs()
{
    m_num = std::abs(m_num);
    return m_num;
}

std::ostream& operator<<(std::ostream& out, Operand opr)
{
    out << opr.get();
    return out;
}


BOOST_PYTHON_MODULE(boost_python)
{
    boost::python::class_<Operand>("Operand", boost::python::init<>())
        .def(boost::python::init<int>())
        .def("get", &Operand::get)
        .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 boost_python
>>> opr1 = boost_python.Operand(10)
>>> opr2 = boost_python.Operand(20)
>>> opr1+opr2
<boost_python.Operand object at 0x000000000389A528>
>>> opr1.get()
30
>>> opr3 = boost_python.Operand(10)
>>> opr3 + 50
<boost_python.Operand object at 0x0000000002EFA528>
>>> opr3.get()
60

//python
>>> import boost_python
>>> opr1 = boost_python.Operand(10)
>>> opr1.get()
10
>>> opr1 += 50
>>> opr1.get()
60
>>> opr2 = boost_python.Operand(30)
>>> opr2.get()
30
>>> opr1 - opr2
<boost_python.Operand object at 0x000000000369A528>
>>> opr1.get()
30
>>> opr1 -= opr2
>>> opr1.get()
0
>>> opr1 - 10
<boost_python.Operand object at 0x000000000369A528>
>>> opr1.get()
-10
>>> opr5 = boost_python.Operand(30)
>>> opr6 = boost_python.Operand(40)
>>> opr5 < opr6
True
>>> opr5 > opr6
False
>>> opr5 - 40
<boost_python.Operand object at 0x0000000002F0A528>
>>> opr5.get()
-10
>>> opr5.abs()
10
>>> opr5.get()
10
>>> str(opr6)
'40'


Object's Lifecycle

  • 使用boost::python::return_internal_reference,表明返回的對象和傳入的那個參數有關,****但實際應用並無意義
  • 使用boost:::python:with_custodian_and_ward,表明參數之間的相互依賴關係,****這個沒有試過
class A
{
public:
    int m_a;
};

class C
{
public:
    A m_a;
};

A& getA(C &pc)
{
    return pc.m_a;
}

BOOST_PYTHON_MODULE(boost_python)
{
    //lifecycle
    boost::python::class_<A>("A", boost::python::init<>())
.def_readwrite("value", &A::m_a);

    boost::python::class_<C>("C", boost::python::init<>())
.def_readwrite("a", &C::m_a);

    boost::python::def("getA", getA, boost::python::return_internal_reference<1>());
}


//python
>>> import boost_python
>>> cObj = boost_python.C()
>>> aObj = boost_python.getA(cObj)
>>> aObj
<boost_python.A object at 0x000000000388A528>
>>> cObj.a
<boost_python.A object at 0x0000000003A15528> //並不是一個對象
>>> del cObj
>>> aObj
<boost_python.A object at 0x000000000388A528> //依然存在

Function Overloading

class Calc
{
public:
    int fun(int a)
    {
        return a;
    }
    int fun(int a, int b)
    {
        return a + b;
    }
    int fun(int a, int b, int c)
    {
        return a + b - c;
    }
};

//重載聲明
int(Calc::*fun1)(int) = &Calc::fun;
int(Calc::*fun2)(int, int) = &Calc::fun;
int(Calc::*fun3)(int, int, int) = &Calc::fun;

BOOST_PYTHON_MODULE(boost_python)
{
    //function overloading of class
    boost::python::class_<Calc>("Calc", boost::python::init<>())
        .def("fun", fun1)
        .def("fun", fun2)
        .def("fun", fun3);
}

//python
>>> import boost_python
>>> c = boost_python.Calc()
>>> c.fun(3)
3
>>> c.fun(3,5)
8
>>> c.fun(3,5,10)
-2
>>> c.fun(3,5,10,2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    Calc.fun(Calc, int, int, int, int)
did not match C++ signature:
    fun(class Calc {lvalue}, int, int, int)
    fun(class Calc {lvalue}, int, int)
    fun(class Calc {lvalue}, int)

Function's Default Parameters of Class

boost::python::optional //構造函數的可選參數標識
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS //定義導出函數名,最少參數和最多參數
class NewCalc
{
public:
    NewCalc()
    {
        m_value = 0;
    }
    NewCalc(int a, double b = 2.0, int c = 10)
    {
        m_value = a + b + c;
    }
    double fun(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(NewCalc_overloads, fun, 1, 3);

BOOST_PYTHON_MODULE(boost_python)
{
    //function's default parameters  of class
    boost::python::class_<NewCalc>("NewCalc", boost::python::init<>())
        .def(boost::python::init<int, boost::python::optional<double, int>>())
        .def("fun", &NewCalc::fun, NewCalc_overloads())
        .def("Value", &NewCalc::Value);

}

//python
>>> import boost_python
>>> cNew = boost_python.NewCalc()
>>> cNew.Value()
0.0
>>> cNew1 = boost_python.NewCalc(10)
>>> cNew1.Value()
22.0
>>> cNew2 = boost_python.NewCalc(10, 30)
>>> cNew2.Value()
50.0
>>> cNew3 = boost_python.NewCalc(10, 30,50)
>>> cNew3.Value()
90.0
>>> cNew3 = boost_python.NewCalc(10, 30, 50, 20)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    NewCalc.__init__(NewCalc, 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 * __


//python
>>> import boost_python
>>> cNew = boost_python.NewCalc()
>>> cNew.fun(10)
8.0
>>> cNew.fun(10, 20)
25.0
>>> cNew.fun(1, 4)
0.0
>>> cNew.fun(1, 4, 10)
-5.0
>>> cNew.fun(1, 4, 10, 5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    NewCalc.fun(NewCalc, int, int, int, int)
did not match C++ signature:
    fun(class NewCalc {lvalue}, int)
    fun(class NewCalc {lvalue}, int, double)
fun(class NewCalc {lvalue}, int, double, int)

Function's Default Parameters

BOOST_PYTHON_FUNCTION_OVERLOADS //定義導出函數名,最少參數和最多參數
double FunDefaultPara(int a, unsigned int b = 2, double c = 3.0)
{
    return a + b + c;
}

BOOST_PYTHON_FUNCTION_OVERLOADS(FunDefaultPara_overload, FunDefaultPara, 1, 3);

BOOST_PYTHON_MODULE(boost_python)
{
    //function's default parameters 
    boost::python::def("FunDefaultPara", FunDefaultPara, FunDefaultPara_overload());
}

>>> import boost_python
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'boost_python']
>>> boost_python.FunDefaultPara(1)
6.0
>>> boost_python.FunDefaultPara(1,5)
9.0
>>> boost_python.FunDefaultPara(1,5,10)
16.0
>>> boost_python.FunDefaultPara(2,5,10)
17.0
>>> boost_python.FunDefaultPara(2,5,10)
17.0
>>> boost_python.FunDefaultPara(2)
7.0
>>> boost_python.FunDefaultPara(2,5,10,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    boost_python.FunDefaultPara(int, int, int, int)
did not match C++ signature:
    FunDefaultPara(int)
    FunDefaultPara(int, unsigned int)
    FunDefaultPara(int, unsigned int, double)

Smart Pointer

boost::python::register_ptr_to_python<TP>()
class Data
{
public:
    void setData(int data)
    {
        m_data = data;
    }

    int getData()
    {
        return m_data;
    }

private:
    int m_data;
};

//smart pointer defined
typedef boost::shared_ptr<Data> DataPtr;

//smart pointer object
DataPtr pData(new Data);

BOOST_PYTHON_MODULE(boost_python)
{
    boost::python::class_<Data>("Data", boost::python::init<>())
        .add_property("data", &Data::getData, &Data::setData);

    boost::python::register_ptr_to_python<DataPtr>();

    boost::python::scope().attr("pData") = pData;
}

//python
>>> import boost_python
>>> boost_python.pData.data
-842150451
>>> boost_python.pData.data = 10
>>> boost_python.pData.data
10
  • 不加入boost::python::register_ptr_to_python描述導出智能指針,導入module時會報錯

  • 只導出智能指針,不導出智能指針指向的類,也會報錯

     

 

2人點贊

 

C++和Python混合編程

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章