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

实战构建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实现过

      

二、系统架构

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

 1

 

 

系统的运行过程为:

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

 

三、实现

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

 

 

 2

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;
}

 

四、结果分析

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

 

 

 3

 

假如直接用 Python.exe 运行上面的 Python 脚本,并不会产生错误,切运行结果正确。这是什么原因引起的呢?

 

从错误提示可以看出加载 MythmaPy 模块失败。这是因为使用 Boost.Python 需要注意一个问题,即在执行脚本之前,需要用 init<ModuleName> 注册封装模块。

加上次限制后,我们就需要对上面的架构做些调整, MythmaPy.dll 需要暴露接口供 PythonConsole.exe 在恰当的时机调用注册该模块。

 

五、小结

       搭建混合系统很简单,麻烦的地方在于 API 的封装。即使采用 dotNet 封装 Native C++ 也是麻烦在这个地方。如果采用一种统一的 API 描述方法,使用工具自动生成封装,这样就可以大大简化封装的复杂度,若可以按需生成不同语言的封装,那更是锦上添花了。

本例的搭建环境为 VS2008 Python2.5 Boost1.38 。完整工程下载 在这里

 

六、广告

4

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值