boost python单步调试_让主程序可以通过python脚本扩展功能及boost.python的使用

/** /file FILENAME /mainpage 让主程序可以通过python脚本扩展功能及boost.python的使用 /brief 本文的内容是:在主程序中嵌入一种脚本语言:python,并且可以通过写python脚本扩展程序功能。 /author 刘凯 mslk.sa@gmail.com /date 20060525 一般情况,为python写个扩展模块(即python脚本中调用扩展模块的功能),或者主程序中调用python解释器执行脚本, 都是单向的。 但要想让python脚本做为主程序的扩展,就像emacs中写lisp来扩展功能,情况就会复杂一点, 即主程序要调用python解释器执行脚本,脚本执行中,要使用主程序的功能或者修改主程序中对象状态。 如果在使用主程序的功能时,主程序又要访问修改当前执行脚本中的python对象的状态或功能,情况会更加复杂。就是必须有双向的通信关系。 如果程序中提供有脚本扩展的能力,好处还是非常大,某些功能用户可以自己实现, 比如有程序中生成了很多对象,都有名字和一些属性,用户可以写段脚本按名字分类整理计算(有了新公式对数据进行处理)输出数据等等。 某些性能无关的功能,用脚本实现真是很方便。 其实嵌入任何脚本都是不错的,脚本语言本身都很简单,但boost.python实在简化了大量大量的工作,所以就选python做扩展,简单嘛。 这里把我的一点经验说一下, 首先,要搞清楚,想从python脚本中访问的功能,就必须做成python的扩展模块(用BOOST_PYTHON_MODULE) 其次,模块中要导出主程序中的根对象和其功能(boost::python::class_),通过根对象可以逐渐访问主程序中其它需要的对象(也要导出), 这也包括需要的一些继承关系为多态(boost::python::wrapper, boost::python::bases)和全局函数(boost::python::def)。 注意: 1.可以建多个扩展模块,有继承关系的类,不能放到不同的模块中,否则子类就不能在脚本中使用了。 2.对于任何模块,如:BOOST_PYTHON_MODULE(PowerApp),要在“Py_Initialize();”调用之后 调一下initPowerApp()(模块名前加init)这个函数,最好也调一下”PyRun_SimpleString("import PowerApp/n");“。 3.def的函数如果有返回值,可能就需要bp::return_value_policy<>,把这个相关的文档先看看 4.新建的mfc项目要把:[项目属性 >> c/c++ >> 语言] 中的[启用运行时类型信息]打开, [项目属性 >> c/c++ >> 代码生成]中的[运行时库]要选 ”多线程[调试] DLL“ 具体用法很简单看boost.python文档,我英文半级的水平都可以看。 为了快速建立信心,这里举个小例子:假定都有这行代码:namespace bp = boost::python 先决定把程序中那个对象作为根来导出,这里根对象的意思是其它对象都可以通过根的属性、函数等直接或间接的访问到,当然可以导出多个根。 如果无法决定,可以先把CWinApp的子类(假设为:CPowerApp)作为根好了,就是AfxGetApp()得到的static_cast一下。 我们在PowerApp模块中提供函数来访问得到它的引用。 主程序中所有的类,用类似的方法均可导出到扩展模块中,更具体的细节:异常的处理,复杂的数据,参考boost.python文档都没什么问题。 */ # include "stdafx.h" # include # include # ifdef _DEBUG # pragma comment(lib, "boost_python-vc71-mt-gd-1_33_1") # else # pragma comment(lib, "boost_python-vc71-mt-1_33_1") # endif # include "power.h" CPowerApp *GetApp() {     assert(dynamic_cast(AfxGetApp()));     return static_cast(AfxGetApp()); } # include /// 演示用的父类 class IPeople {     std::string _name; public:     virtual void msg_box() = 0;     std::string const& get_name();     void set_name(std::string const&); }; /// 演示用的子类 class ApplicationAuthor : public IPeople {     std::wstring _content;        // 对程序的一下说明 public:     void msg_box();     void set_content(std::wstring const&);    }; /// 伪造一个CPowerApp的成员函数 /**    如果改为成员函数,需要在CPowerApp加一个成员变量和函数       -# ApplicationAuthor _author;    -# ApplicationAuthor &GetAuthor();         -# ApplicationAuthor &GetAuthor() {return _author;} // 不要inline,取不到地址了    修改”关于“对话框显示:_author.get_name() 和 _author.get_content()这两个成员的内容  */ ApplicationAuthor& CPowerApp_GetAuthor(CPowerApp *pApp) {     static ApplicationAuthor suppose_PowerApp_memeber; // 假定为CPowerApp的成员变量     return suppose_PowerApp_memeber; } namespace bp = boost::python; BOOST_PYTHON_MODULE(PowerApp) {     bp::def("GetApp", &GetApp, bp::return_value_policy<:reference_existing_object>());          bp::class_("App")         .def("About", &CPowerApp::OnAppAbout)         .def("GetAuthor", &CPowerApp_GetAuthor, bp::return_value_policy<:reference_existing_object>())         ; } /// 对于抽象类,需要包装,把纯虚函数处理一下,具体参考文档 struct IPeopleWrapper : public IPeople, public bp::wrapper {     void msg_box() {this->get_override("msg_box")();} }; BOOST_PYTHON_MODULE(DataManager) {     bp::class_("IPeople")         .def("set_name", &IPeople::set_name)         .def("get_name", &IPeople::get_name, bp::return_internal_reference<>())         .def("msg_box", &IPeople::msg_box)         ;     bp::class_ >("ApplicationAuthor")         .def("set_content", &ApplicationAuthor::set_content)         ; } std::string const& IPeople::get_name() {return _name;} void IPeople::set_name(std::string const& v) {_name = v;} void ApplicationAuthor::set_content(std::wstring const& c) {_content = c;} void ApplicationAuthor::msg_box() {MessageBoxW(NULL, _content.data(), L"PowerApp good! Content:", MB_OK);     MessageBoxA(NULL, get_name().data(), "IPeople::name", MB_OK);} /** 遗留的问题:     -# .def的函数,std::string、wstring作为函数的返回值有问题,但作为函数的参数可以  */ /// CPowerApp构造函数调用这个函数 void InitPy() {     Py_Initialize();          PyRun_SimpleString("import wx/n");     initPowerApp();     PyRun_SimpleString("import PowerApp/n");          /// 模块太多的话,就需要简化一下了,定义一个宏,把模块名传入宏 # define INIT_PM(v) init##v##();PyRun_SimpleString("import " #v "/n");              INIT_PM(DataManager);              # undef INIT_PM } /// CPowerApp的析构调用这个函数:Py_Finalize() /// 最后一下,加个菜单调一下这个函数, void pyShell() {         PyRun_SimpleString("from PyShell import main/nmain()/n"); } /** 使用指南 要同时安装好:     python24(http://www.python.org)     wxPython(http://www.wxpython.org) 编译好:boost.python(http://www.boost.org)     编译方法很简单,参考文章http://blog.csdn.net/mslk/archive/2005/11/08/525278.aspx的最后说明。     bjam --with-python-root=python24主目录路径 将PowerApp.exe,boost_python* 放入python24的主目录,执行调出pyShell dir (PowerApp) dir (DataManager) app = PowerApp.GetApp() app.About() a = app.GetAuthor() a.msg_box() a.set_name("LiuKai mslk.sa@gmail.com") a.set_content("boost.python Very Good!") a.msg_box() app.About() …………………… */ /** 菜鸟指南:     打开vs2003,[文件 >> 新建 >> 项目]     选 [mfc >> mfc 应用程序],名称:Power,完成     [工具 >> 选项 >> 项目 >> vc++目录]     配置[包含文件]添加boost,和python24/include     配置[库文件]添加boost/bin和python24/libs     把这篇文章保存到一个cpp后缀的文件,加入项目中     找到CPowerApp::CPowerApp函数,添加函数调用         InitPy();     CPowerApp构造函数前面加上声明:         void InitPy();         void pyShell();              打开资源,添加一个菜单名:pyShell,消息处理函数选为CPowerApp的成员, 消息处理函数内调用:     pyShell();        再强调一下:     [项目属性 >> c/c++ >> 语言] 中的[启用运行时类型信息]打开,     [项目属性 >> c/c++ >> 代码生成]中的[运行时库]要选 ”多线程[调试] DLL“          编译后,将Power.exe拷入Python24的主目录,执行后点菜单,弹出来pyShell, 按照使用指南键入命令,即可看到效果。 */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值