您的位置:首页 > 编程语言 > C语言/C++

实战构建Python和C++混合系统

2011-02-17 19:49 726 查看

实战构建Python和C++混合系统
收藏



此文于2009-09-16被推荐到CSDN首页

如何被推荐?

关于

C++


Python
之间互相调用的问题,可以查找到很多资料。本文将主要从解决实际问题的角度看如何构建一个

Python


C++
混合系统。

力为 2009

一、概念

混合系统

:采用多种语言构建的系统。比如

Native C++


dotNet
的混合系统,

Python/Lua


C++
的混合系统。

Python


C++
各有各的优缺点,构建两者混合系统的主要目的就是利用

Python
的灵活性和

C++
高效性,增加程序的扩展性。当然还有其他好处,此处就不展开谈了。脚本语言有很多,至于为什么不采用其他的(如

Lua


Ruby
等),这里也不考虑。脚本语言的采用主要是个人喜好的问题。采用

Lua
可以查到很多资料,以前也曾用

LuaBind实现过



二、系统架构

混合系统可以简化成如下模型:



系统的运行过程为:

首先在应用程序中嵌入脚本语言解析器,然后用脚本语言提供的
C/C++ API
封装已有的
C++
功能库,再用脚本调用封装的服务。此后,应用层便可以执行脚本里的内容,其效果与应用层直接调用服务层类似。

三、实现

本例中采用脚本语言
Python
,因此主要工作为在应用层嵌入
Python
解析器,用
Python
封装服务层。为了说明问题,应用层的实现为
PythonConsole.ex
,服务层的实现为
Mythma.dll
,封装层为
MythmaPy.dll




1

、假定
Mythma.dll
中的一个类为
CHelloWorld






class MythmaAPI CHelloWorld











{





public:



CHelloWorld(void);



~

CHelloWorld(void);







void
SetId(
int
nId)




{ m_Id
=
nId;}





int
GetId()
const





{
return
m_Id; }







private:





int m_Id;



}


;





2

、现在用
Boost.Python

封装该类:



#include
"
HelloWorld.h
"



#include
<
boost
/
python.hpp
>



using

namespace
boost::python;





BOOST_PYTHON_MODULE(MythmaPy)







{



class_
<
CHelloWorld
>
(
"
CHelloWorld
"
)



.def(
"
SetId
"
,
&
CHelloWorld::SetId)



.def(
"
GetId
"
,
&
CHelloWorld::GetId)



;



}



3

、在
Python

脚本中调用该封装



#
import MythmaPy



from
MythmaPy
import

*



world
=
CHelloWorld()



world.SetId(
100
)



print
world.GetId()

4

、在
PythonConsole.exe

中嵌入
Python

解析器



int
main(
int
argc,
char

**
argv)







{



//
Initialize the interpreter



Py_Initialize();





if
(python::handle_exception(exec_mythma))







{



if
(PyErr_Occurred())







{



BOOST_ERROR(
"
Python Error detected
"
);



PyErr_Print();



}



else







{



BOOST_ERROR(
"
A C++ exception was thrown for which
"



"
there was no exception translator registered.
"
);



}



}





char
ch;



std::cin
>>
ch;



//
Boost.Python doesn't support Py_Finalize yet, so don't call it!



return
boost::report_errors();



}




PythonConsole

中调用
Python

脚本



void
exec_mythma()







{



std::cout
<<

"
exec extension module Mythma


"

<<
std::endl;





python::dict global;



python::
object
result
=
python::exec_file(



"
.//axxscript.py
"
, global, global);







python::
object
world
=
global[
"
world
"
];



CHelloWorld
&
py
=
python::extract
<
CHelloWorld
&>
(world) BOOST_EXTRACT_WORKAROUND;





std::cout
<<
py.GetId()
<<
std::endl;





std::cout
<<

"
success!
"

<<
std::endl;



}

四、结果分析

到此为止,一切感觉都很良好。但假如现在就运行程序,为得到如下的错误:



假如直接用
Python.exe

运行上面的
Python

脚本,并不会产生错误,切运行结果正确。这是什么原因引起的呢?

从错误提示可以看出加载
MythmaPy

模块失败。这是因为使用
Boost.Python

需要注意一个问题,即在执行脚本之前,需要用
init<ModuleName>

注册封装模块。

加上次限制后,我们就需要对上面的架构做些调整,
MythmaPy.dll

需要暴露接口供
PythonConsole.exe

在恰当的时机调用注册该模块。

五、小结

搭建混合系统很简单,麻烦的地方在于
API

的封装。即使采用
dotNet

封装
Native C++

也是麻烦在这个地方。如果采用一种统一的
API

描述方法,使用工具自动生成封装,这样就可以大大简化封装的复杂度,若可以按需生成不同语言的封装,那更是锦上添花了。

本例的搭建环境为
VS2008


Python2.5


Boost1.38

。完整工程下载
在这里



六、广告

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: