zoukankan      html  css  js  c++  java
  • 实战构建Python和C++混合系统

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

                                             力为 2009

     

    一、概念

        混合系统:采用多种语言构建的系统。比如Native C++dotNet的混合系统,Python/LuaC++的混合系统。

    PythonC++各有各的优缺点,构建两者混合系统的主要目的就是利用Python的灵活性和C++高效性,增加程序的扩展性。当然还有其他好处,此处就不展开谈了。脚本语言有很多,至于为什么不采用其他的(如LuaRuby等),这里也不考虑。脚本语言的采用主要是个人喜好的问题。采用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描述方法,使用工具自动生成封装,这样就可以大大简化封装的复杂度,若可以按需生成不同语言的封装,那更是锦上添花了。

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

     

    六、广告

    4

  • 相关阅读:
    "Login failed for user 'NT AUTHORITYSYSTEM'. 原因: 无法打开明确指定的数据库。"异常处理
    Windows 服务器自动重启定位
    扩展数据组码和说明
    C# CAD二次开发 扩展数据的几个重要方法
    CAD二次开发 eLockViolation 错误解决方法
    看kean 博客---- CAD.NET
    一个GIS研究生的自白
    C# 调用CAD系统命令
    <转载>Win32控制台工程中创建窗口
    <转载>无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用
  • 原文地址:https://www.cnblogs.com/aiwz/p/6333124.html
Copyright © 2011-2022 走看看