实战构建Python和C++混合系统
2011-02-17 19:49
726 查看
实战构建Python和C++混合系统
收藏
![](http://blog.csdn.net/images/tuijian.gif)
此文于2009-09-16被推荐到CSDN首页
如何被推荐?
关于C++
和
Python
之间互相调用的问题,可以查找到很多资料。本文将主要从解决实际问题的角度看如何构建一个
Python
和
C++
混合系统。
力为 2009
一、概念
混合系统
:采用多种语言构建的系统。比如
Native C++
和
dotNet
的混合系统,
Python/Lua
和
C++
的混合系统。
Python
和
C++
各有各的优缺点,构建两者混合系统的主要目的就是利用
Python
的灵活性和
C++
高效性,增加程序的扩展性。当然还有其他好处,此处就不展开谈了。脚本语言有很多,至于为什么不采用其他的(如
Lua
、
Ruby
等),这里也不考虑。脚本语言的采用主要是个人喜好的问题。采用
Lua
可以查到很多资料,以前也曾用
LuaBind实现过
。
二、系统架构
混合系统可以简化成如下模型:
![](http://p.blog.csdn.net/images/p_blog_csdn_net/mythma/EntryImages/20090915/arch1.jpg)
系统的运行过程为:
首先在应用程序中嵌入脚本语言解析器,然后用脚本语言提供的
C/C++ API
封装已有的
C++
功能库,再用脚本调用封装的服务。此后,应用层便可以执行脚本里的内容,其效果与应用层直接调用服务层类似。
三、实现
本例中采用脚本语言
Python
,因此主要工作为在应用层嵌入
Python
解析器,用
Python
封装服务层。为了说明问题,应用层的实现为
PythonConsole.ex
,服务层的实现为
Mythma.dll
,封装层为
MythmaPy.dll
。
![](http://p.blog.csdn.net/images/p_blog_csdn_net/mythma/EntryImages/20090915/arch2.jpg)
1
、假定
Mythma.dll
中的一个类为
CHelloWorld
:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
class MythmaAPI CHelloWorld
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/dbf989d57862681739b642d8621fe1f0.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/918e8df969f9f8c8d002f25cda86cade.gif)
{
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
public:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
CHelloWorld(void);
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
~
CHelloWorld(void);
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/f70a0fde2b51b7dd92a70e712e540cf6.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/edb48e6f68462ea23d9a824f01de40c5.gif)
void
SetId(
int
nId)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/918e8df969f9f8c8d002f25cda86cade.gif)
{ m_Id
=
nId;}
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/f70a0fde2b51b7dd92a70e712e540cf6.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/edb48e6f68462ea23d9a824f01de40c5.gif)
int
GetId()
const
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/918e8df969f9f8c8d002f25cda86cade.gif)
{
return
m_Id; }
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
private:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
int m_Id;
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/0ac3a2d53663ec01c7f7225264eeefae.gif)
}
;
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
2
、现在用
Boost.Python
封装该类:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
#include
"
HelloWorld.h
"
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
#include
<
boost
/
python.hpp
>
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
using
namespace
boost::python;
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
BOOST_PYTHON_MODULE(MythmaPy)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/dbf989d57862681739b642d8621fe1f0.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/918e8df969f9f8c8d002f25cda86cade.gif)
{
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
class_
<
CHelloWorld
>
(
"
CHelloWorld
"
)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
.def(
"
SetId
"
,
&
CHelloWorld::SetId)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
.def(
"
GetId
"
,
&
CHelloWorld::GetId)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
;
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/0ac3a2d53663ec01c7f7225264eeefae.gif)
}
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
3
、在
Python
脚本中调用该封装
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
#
import MythmaPy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
from
MythmaPy
import
*
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
world
=
CHelloWorld()
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
world.SetId(
100
)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
world.GetId()
4
、在
PythonConsole.exe
中嵌入
Python
解析器
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
int
main(
int
argc,
char
**
argv)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/dbf989d57862681739b642d8621fe1f0.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/918e8df969f9f8c8d002f25cda86cade.gif)
{
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
//
Initialize the interpreter
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
Py_Initialize();
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
if
(python::handle_exception(exec_mythma))
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/f70a0fde2b51b7dd92a70e712e540cf6.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/edb48e6f68462ea23d9a824f01de40c5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/918e8df969f9f8c8d002f25cda86cade.gif)
{
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
if
(PyErr_Occurred())
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/f70a0fde2b51b7dd92a70e712e540cf6.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/edb48e6f68462ea23d9a824f01de40c5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/918e8df969f9f8c8d002f25cda86cade.gif)
{
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
BOOST_ERROR(
"
Python Error detected
"
);
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
PyErr_Print();
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/4a5daaec04350a363f186a4d2c5ed6ce.gif)
}
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
else
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/f70a0fde2b51b7dd92a70e712e540cf6.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/edb48e6f68462ea23d9a824f01de40c5.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/918e8df969f9f8c8d002f25cda86cade.gif)
{
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
BOOST_ERROR(
"
A C++ exception was thrown for which
"
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
"
there was no exception translator registered.
"
);
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/4a5daaec04350a363f186a4d2c5ed6ce.gif)
}
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/4a5daaec04350a363f186a4d2c5ed6ce.gif)
}
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
char
ch;
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
std::cin
>>
ch;
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
//
Boost.Python doesn't support Py_Finalize yet, so don't call it!
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
return
boost::report_errors();
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/0ac3a2d53663ec01c7f7225264eeefae.gif)
}
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
在
PythonConsole
中调用
Python
脚本
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/cbef093dcc044b2793832001e2365e43.gif)
void
exec_mythma()
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/dbf989d57862681739b642d8621fe1f0.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/918e8df969f9f8c8d002f25cda86cade.gif)
{
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
std::cout
<<
"
exec extension module Mythma
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/918e8df969f9f8c8d002f25cda86cade.gif)
"
<<
std::endl;
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
python::dict global;
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
python::
object
result
=
python::exec_file(
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
"
.//axxscript.py
"
, global, global);
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
python::
object
world
=
global[
"
world
"
];
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
CHelloWorld
&
py
=
python::extract
<
CHelloWorld
&>
(world) BOOST_EXTRACT_WORKAROUND;
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
std::cout
<<
py.GetId()
<<
std::endl;
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/df37983f39daa189b8c814e01a6a9011.gif)
std::cout
<<
"
success!
"
<<
std::endl;
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/0ac3a2d53663ec01c7f7225264eeefae.gif)
}
四、结果分析
到此为止,一切感觉都很良好。但假如现在就运行程序,为得到如下的错误:
假如直接用
Python.exe
运行上面的
Python
脚本,并不会产生错误,切运行结果正确。这是什么原因引起的呢?
从错误提示可以看出加载
MythmaPy
模块失败。这是因为使用
Boost.Python
需要注意一个问题,即在执行脚本之前,需要用
init<ModuleName>
注册封装模块。
加上次限制后,我们就需要对上面的架构做些调整,
MythmaPy.dll
需要暴露接口供
PythonConsole.exe
在恰当的时机调用注册该模块。
五、小结
搭建混合系统很简单,麻烦的地方在于
API
的封装。即使采用
dotNet
封装
Native C++
也是麻烦在这个地方。如果采用一种统一的
API
描述方法,使用工具自动生成封装,这样就可以大大简化封装的复杂度,若可以按需生成不同语言的封装,那更是锦上添花了。
本例的搭建环境为
VS2008
,
Python2.5
,
Boost1.38
。完整工程下载
在这里
。
六、广告
相关文章推荐
- 实战构建Python和C++混合系统
- 实战构建Python和C++混合系统
- 实战构建Python和C++混合系统
- 使用Boost.Python构建混合系统
- 用Boost.Python构建混合系统
- 用Boost.Python构建混合系统
- 用Boost.Python构建混合系统
- 机器学习实战python版归一化数值和测试kNN算法以及构建完整可用系统
- 用Boost.Python构建混合系统
- 使用Boost.Python构建混合系统
- 构建高可扩Web架构和分布式系统实战(上)
- 【Spark亚太研究院系列丛书】Spark实战高手之路-第一章 构建Spark集群-安装Ubuntu系统(3)
- Win7 32位系统下Sublime text 3的安装以及配置C/C++、java、python的开发环境方法
- 【大话QT之十六】使用ctkPluginFramework插件系统构建项目实战
- C/C++构建系统 GNU autotool
- Python爬虫实战——模拟登录教务系统
- Python3 利用asynico协程系统构建生产消费模型
- aiml语言python对话系统构建
- 用Boost.python构建游戏脚本系统的尝试
- 5种语言混合编程:C++、JS、python、Lisp、汇编