参考
https://www.jianshu.com/p/bc0f18b60c89
人果然是健忘的,几年前用过这个,转眼就忘记了。再次拾起来,记录下。
忘记了去掉lib**.so的lib.
# 将这些库的前缀lib去掉,因为会扰乱Python模块的查找
set_target_properties( botcurve PROPERTIES PREFIX "")
#set_target_properties( ${SERVER_LIB} PROPERTIES PREFIX "")
sudo apt-get install libboost-python-dev
bot_curve.cpp
#include
#include
#include
#include
#include
#include
#include
using namespace boost::python;
#include
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", boost::python::init())
.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
--------转自
JasonLiThirty已关注
0.0972019.02.11 22:12:32字数 868阅读 2,349
boost::python用于将C++的函数和对象导出,方便python调用对象和方法,用来实现C++和Python的混合编程。
编译boost::python库和建立VS工程的详细步骤参考boost::python实现C++和Python的混合编程(编译和配置)
以下是各种基本类型导出的格式和关键字
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!'
boost::python::scope().attr
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")
.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")
.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")
.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 "", line 1, in
AttributeError: 'module' object has no attribute 'yes'
>>> boost_python.no
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'module' object has no attribute 'no'
>>> msg = boost_python.Message()
>>> msg.yes
1
>>> msg.no
0
>>>
#include
#include
#include
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")
.def("f", &X::f)
;
// Define a class Y in the current scope, X
class_("Y")
.def("g", &X::Y::g)
;
}
//python
>>> import nested
>>> nested.yes
1
>>> y = nested.X.Y()
>>> y.g()
421
boost::python::class_("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")
.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'
boost::python::class_("TName", boost::python::init())
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", boost::python::init()) //default constructor
.def(boost::python::init()) //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 "", line 1, in
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,class std::allocator >)
>>> s = boost_python.Sum("hello")
>>> s.get()
'hello'
>>> sum = boost_python.Sum(3,4)
>>> sum.result()
7.0
.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", boost::python::init())
.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 "", line 1, in
AttributeError: can't set attribute
>>> v.value = "hello" //Error
Traceback (most recent call last):
File "", line 1, in
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_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", 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 "", line 1, in
AttributeError: 'NewMessage' object has no attribute 'get'
>>> newMsg.msg
''
>>> newMsg.msg = "hello"
>>> newMsg.msg
'hello'
boost::python::class_>("TName")
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", boost::python::init<>())
.def("getName", &Base::getName);
boost::python::class_>("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());
}
//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 "", line 1, in
Boost.Python.ArgumentError: Python argument types in
boost_python.DerivedName(Base)
did not match C++ signature:
DerivedName(class Derived * __ptr64)
>>> b.getName()
'Base'
boost::python::wrapper
boost::python::class_
boost::python::pure_virtual
class BasePVF
{
public:
virtual ~BasePVF() {}
virtual int f() = 0;
};
class BasePVFWrap : public BasePVF, public boost::python::wrapper
{
public:
int f()
{
return this->get_override("f")();
}
};
BOOST_PYTHON_MODULE(boost_python)
{
//pure virtual function
boost::python::class_("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 "", line 1, in
RuntimeError: Pure virtual function called
>>> class DerivedPVF(boost_python.BasePVF):
... def f(self):
... return 50
...
>>> object_derived_pvf = DerivedPVF()
>>> object_derived_pvf.f()
50
class BaseVF
{
public:
virtual ~BaseVF() {}
virtual int f() { return 0; }
};
class BaseVFWrap : public BaseVF, public boost::python::wrapper
{
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_("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
.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", boost::python::init<>())
.def(boost::python::init())
.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
>>> opr1.get()
30
>>> opr3 = boost_python.Operand(10)
>>> opr3 + 50
>>> 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
>>> opr1.get()
30
>>> opr1 -= opr2
>>> opr1.get()
0
>>> opr1 - 10
>>> opr1.get()
-10
>>> opr5 = boost_python.Operand(30)
>>> opr6 = boost_python.Operand(40)
>>> opr5 < opr6
True
>>> opr5 > opr6
False
>>> opr5 - 40
>>> opr5.get()
-10
>>> opr5.abs()
10
>>> opr5.get()
10
>>> str(opr6)
'40'
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", boost::python::init<>())
.def_readwrite("value", &A::m_a);
boost::python::class_("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
>>> cObj.a
//并不是一个对象
>>> del cObj
>>> aObj
//依然存在
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", 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 "", line 1, in
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)
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", boost::python::init<>())
.def(boost::python::init>())
.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 "", line 1, in
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 "", line 1, in
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)
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 "", line 1, in
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)
boost::python::register_ptr_to_python()
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 DataPtr;
//smart pointer object
DataPtr pData(new Data);
BOOST_PYTHON_MODULE(boost_python)
{
boost::python::class_("Data", boost::python::init<>())
.add_property("data", &Data::getData, &Data::setData);
boost::python::register_ptr_to_python();
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
2人点赞
C++和Python混合编程