python代码怎么封装成dll_【转】利用Boost.Python将C++代码封装为Python模块

用Boost.Python将C++代码封装为Python模块

一. 基础篇

借助Boost.Python库可以将C/C++代码方便、快捷地移植到python模块当中,实现对python模块的扩充。首先,将C++下的代码编译为动态库,并将生成的动态库命名为封装模块的名字,如:用BOOST_PYTHON_MODULE(Module_Name)宏对需要导出的函数、全局变量、类等导入Python的Module_Name模块,此时生成的动态库需要更名为Module_Name.pyd。然后,将Module_Name.pyd放在python的系统搜索目录中(通常是%PYTHON_PATH%\DLLs目录)。最后,在IDLE GUI界面或是python脚本中执行import Module_Name,这样就可以在python复用C++中定义的函数、类等而不必重写。

xuyuan77标注: 如果出现dll无法加载的情况,可以用depends工具查看是否有依赖的dll缺失,比如我在ipython中importBoostPython_Module_Abs 时无法load dll,是因为 DLLS目录下没有依赖的boost_python3-vc140-mt-x64-1_66.dll文件。

我测试的时候用的是boost 1_66版本,python3.5版本。原作者的代码有很多错误,我注释了代码,只试了import BoostPython_Module_Abs 模块。可以成功运行。

二. 实例篇

下面的实例代码主要针对抽象类、带默认实现虚函数的类、类的成员函数及操作符重载、带默认参数的函数(包括构造函数)、派生类、纯虚函数、返回对象及字符串的函数等的封装方法,基本概括了C+扩展到python模块的常见类型。

//boostpython_abs.h

#include #ifndef BOOSTPYTHON_ABS_H#define BOOSTPYTHON_ABS_H

/**brief:

* wrap c/c++ code as dll and export the class/function interfaces

* to python as modules with boost-library

*author:

* hank

*history:

* created 2012-07-13*/#ifndef BSTPABS_API#define BSTPABS_API __declspec(dllimport)

#else

#define BSTPABS_API __declspec(dllexport)

#endif

/** 1.export the abstract class into python module

* 2.abstract class with member over-load functions|operators*/

classBSTPABS_API CPhone

{public:enum Mode { CANCONNECTED = 0, CONNECTED, PAUSE, DISCONNECTED };public:

CPhone(std::string owner = "") {}virtual int make_call(int phone_num) = 0;virtual std::string make_call(std::string name) = 0;virtual CPhone& operator << (int phone_num) = 0;virtual CPhone& operator << (std::string name) = 0;

};//here,wrap the CPhone class

class CPhoneWrap :publicCPhone,public boost::python::wrapper{public:int make_call(intphone_num);

std::string make_call(std::stringname);

CPhone& operator <<(intphone_num);

CPhone& operator << (std::stringname);

};#endif//BOOSTPYTHON_ABS_H

//boostpython_abs.cpp

#include#include"boostpython_abs.h"

//define function pointers of overload functions

int (CPhone::*make_call1)(int) = &CPhone::make_call;

std::string(CPhone::*make_call2)(std::string) = &CPhone::make_call;

CPhone& (CPhone::*o1)(int) = &CPhone::operator<<;

CPhone& (CPhone::*o2)(std::string) = &CPhone::operator<<;int CPhoneWrap::make_call(intphone_num)

{return this->get_override("make_call1")();

}

std::string CPhoneWrap::make_call(std::stringname)

{return this->get_override("make_call2")();

}

CPhone& CPhoneWrap::operator << (intphone_num)

{return boost::python::call(this->get_override("o1").ptr());

}

CPhone& CPhoneWrap::operator <<(std::stringname)

{return boost::python::call(this->get_override("o2").ptr());

}/** Boost.Python Module Export Code bellow*/BOOST_PYTHON_MODULE(BoostPython_Module_Abs)

{using namespaceboost::python;

class_("CPhone")

.def("<<", pure_virtual(o1), return_internal_reference<>())

.def("<<", pure_virtual(o2), return_internal_reference<>())

.def("make_call", pure_virtual(make_call1))

.def("make_call", pure_virtual(make_call2))

;

enum_("Mode")

.value("CANCONNECTED", CPhoneWrap::Mode::CANCONNECTED)

.value("CONNECTED", CPhoneWrap::Mode::CONNECTED)

.value("PAUSE", CPhoneWrap::Mode::PAUSE)

.value("DISCONNECTED", CPhoneWrap::Mode::DISCONNECTED)

;

}

//boostpython_com.h

#ifndef BOOSTPYTHON_COM_H#define BOOSTPYTHON_COM_H#include"boostpython_abs.h"#ifndef BSTPCOM_API#define BSTPCOM_API __declspec(dllimport)

#else

#define BSTPCOM_API __declspec(dllexport)

#endif

/** 1.common class with member over-load functions|operators

* 2.with default parameter in constructor function*/

classBSTPCOM_API CPerson

{private:intphone_num;

std::stringname;

CPhone::Mode mode;public:

CPerson() {/*initializtion here*/}

CPerson(int num, CPhone::Mode aMode =CPhone::CANCONNECTED)

{this->mode =aMode;

}void set(intnum)

{this->phone_num =num;

}void set(std::stringaName)

{this->name =aName;

}void setall(int num, std::string name = "") {/*do something here*/}

CPerson&operator<<(int phone_num) { return *this; }

CPerson&operator<<(std::string name) { return *this; }

CPerson& write(int phone_num) { return *this; }

CPerson& write(std::string name) { return *this; }

};#endif//BOOSTPYTHON_COM_H

//boostpython_com.cpp

#include#include"boostpython_com.h"#include"boostpython_abs.h"

/** the function pointers of overload functions*/

//void (CPerson::*set1)(int) = &CPerson::set;//

//void (CPerson::*set2)(std::string) = &CPerson::set;//

//CPerson& (CPerson::*write1)(int) = &CPerson::write;//

//CPerson& (CPerson::*write2)(std::string) = &CPerson::write;

/** Boost.Python Module Export Code bellow*/

//BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(setall_overload, setall, 1, 2)//

//BOOST_PYTHON_MODULE (BoostPython_Module_Com)//

//{//

//using namespace boost::python;//

//class_("CPerson")//

//.def(init >())//

//.def(self << int())//

//.def(self << std::string())//

//.def("setall", &CPerson::setall, setall_overload())//

//.def("set", set1)//

//.def("set", set2)//

//.def("write", write1)//

//.def("write", write2);//

//}

//boostpython_info.h

#ifndef BOOSTPYTHON_INFO_H#define BOOSTPYTHON_INFO_H#include"boostpython_abs.h"#include"boostpython_com.h"#include //included in dir %PYTHON_PATH%\include

#include#ifndef BSTPINFO_API#define BSTPINFO_API __declspec(dllimport)

#else

#define BSTPINFO_API __declspec(dllexport)

#endif

/** 1. virtual functions with default implements

* 2. stl export

* 3. with char* return function,must wrap it

* 4. global function(c-style)*/

classBSTPINFO_API CInfo

{public:virtual std::string get_info() { return "None Info"; }

};class BSTPINFO_API CMessageInfo :publicCInfo

{public:virtual std::string get_info() { return "Message Info"; }

};classBSTPINFO_API CContact

{

std::vectorm_vec;public:

std::vectorget_contact_person()

{returnm_vec;

}

CInfo* get_contact_style() { return new(std::nothrow)CMessageInfo(); }void set_contact_style(CInfo*) {/*todo:xxx*/}char* get_info() { return "return char* in python"; }//you should wrap char* f(),however,const char* f() this not needed

PyObject* get_info_wrap() { return Py_BuildValue("s", get_info()); }

};#endif //BOOSTPYTHON_INFO_H

#include #include"boostpython_info.h"

class CInfoWrap :publicCInfo,public boost::python::wrapper{public:

std::stringget_info()

{if (boost::python::override g = this->get_override("get_info"))

{returnget_info();

}returnCInfo::get_info();

}

};class CMessageInfoWrap :publicCMessageInfo,public boost::python::wrapper{

std::stringget_info()

{if (boost::python::override g = this->get_override("get_info"))

{returnget_info();

}returnCMessageInfo::get_info();

}

};//define export methods of string-vector into python

typedef std::vectorCStringVector;void push_back(CStringVector& vec, std::stringstr)

{

vec.push_back(str);

}

std::string pop_back(CStringVector&vec)

{

std::string ret =vec.back();

vec.pop_back();returnret;

}/** Boost.Python Module code*/

//

//BOOST_PYTHON_MODULE(BoostPython_Module_Info)//

//{//

//using namespace boost::python;//

// //export vector in c++ as list in python//

//class_("CStringVector")//

//.def("push_back", push_back)//

//.def("pop_back", pop_back)//

//.def("__iter__", boost::python::iterator())//

//;//

//class_("CInfo")//

//.def("get_info", &CInfo::get_info)//

//;//

//class_, boost::noncopyable>("CMessageInfo")//

//.def("get_info", &CMessageInfo::get_info)//

//;//

//class_("CContact")//

//.def("get_contact_person", &CContact::get_contact_person)//

//.def("get_contact_style", &CContact::get_contact_style, return_value_policy())//

//.def("set_contact_style", &CContact::set_contact_style)//

//.def("get_info", &CContact::get_info_wrap);//

//}

#!/bin/python

#demo.py'''brief:

demonstratione of C/C++dll export into python modules

author:

hank/2012-07-13

'''import BoostPython_Module_Abs

import BoostPython_Module_Com

import BoostPython_Module_Info

info=BoostPython_Module_Info.CMessageInfo()

contact=BoostPython_Module_Info.CContact()

contact.set_contact_style(info)

getinfo=contact.get_contact_style()

print(type(getinfo)) #the type should be CMessageInfo instance

chars=contact.get_info()

print(chars)

三. 参考文献

2. python-2.7.2自带文档

转自:http://blog.csdn.net/scuhank/article/details/7769342

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2021 CSDN 皮肤主题: 1024 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值