zoukankan      html  css  js  c++  java
  • 使用SWIG实现Python调用C/C++代码

    转自:http://cering.github.io/2015/12/08/%E4%BD%BF%E7%94%A8SWIG%E5%AE%9E%E7%8E%B0Python%E8%B0%83%E7%94%A8C-C-%E4%BB%A3%E7%A0%81/

    SWIG是个帮助使用C或者C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具。
    SWIG能应用于各种不同类型的语言,包括常用脚本编译语言,例如Perl, PHP, Python, Tcl, Ruby 和 PHP。
    SWIG普遍应用于创建高级语言解析或汇编程序环境、用户接口、作为一种用来测试C/C++或进行原型设计的工具。

    工作中碰到了一个小问题:有一个加密/解密的程序原本是用C++语言写的,后来需要用Python来实现调用。简单粗暴的办法是照着C++代码重写一个Python版本的程序,但是很麻烦,还会带来以下问题:

    • 时间成本,开发方面需要些代价
    • 维护成本,需要自己维护,重复造轮子
    • 代码冗余,多套代码,不易维护

    后来经老手介绍,知道可以用SWIG来把C++的代码封装成Python库,供Python调用。
    SWIG (Simplified Wrapper and Interface Generator) 是用来为C和C++程序构造脚本语言接口的软件开发工具。SWIG 实际上是一个编译器,获取C/C++的声明,用一个壳包起来,以便通过其他语言访问这些声明。因此,SWIG 最大的好处就是将脚本语言的开发效率和 C/C++ 的运行效率结合起来

    1 原始文件

    编写好原始的h和cpp文件,示例如下:

    //File: EncryptTool.h
    int EncryptFile(const char *szInputFile, const char *szOutputFile);
    int DecryptFile(const char *szInputFile, const char *szOutputFile);
    
    
    //File: EncryptTool.cpp
    int EncryptFile(const char *szInputFile, const char *szOutputFile)
    {
        ... //省略实现代码
    }
    
    int DecryptFile(const char *szInputFile, const char *szOutputFile)
    {
        ... //省略实现代码
    }

    2 编写.i接口文件

    新增加文件EncryptTool.i,内容如下:

    //File: EncryptTool.i
    %module EncryptTool
    %{
    #define SWIG_FILE_WITH_INIT
    #include "EncryptTool.h"
    %}
    
    int EncryptFile(const char *szInputFile, const char *szOutputFile);
    int DecryptFile(const char *szInputFile, const char *szOutputFile);

    .i接口文件中主要包含了三个部分:

    1. %module后面的名字是被封装的模块名称,Python通过这个名称加载程序。
    2. %{...%}之间所添加的内容,一般包含此文件需要的一些函数声明和头文件。
    3. 最后一部分,声明了要封装的函数和变量。

    如果把要封装的函数声明部分写在了头文件里,最后一部分直接用%include包含头文件名也行:

    //File: EncryptTool.i
    %module EncryptTool
    %{
    #define SWIG_FILE_WITH_INIT
    #include "EncryptTool.h"
    %}
    
    %include "EncryptTool.h"

    两种.i文件的效果是一样的,比较建议使用第二种方法,能够简化接口文件

    3 封装代码

    执行以下命令对c++代码进行封装:

    swig -python -c++ EncryptTool.i

    执行完毕后会生成EncryptTool.py和EncryptTool_wrap.cxx这两个文件,相当于将原cpp文件进行了封装,wrap了一层

    4 生成动态链接库

    编写setup.py文件,用于自动化编译动态链接库:

    #File: setup.py
    #!/usr/bin/python2.7
    
    from distutils.core import setup, Extension
    
    #生成一个扩展模块
    pht_module = Extension('_EncryptTool', #模块名称,必须要有下划线
                            sources=['EncryptTool_wrap.cxx', #封装后的接口cxx文件
                                     'base32.cpp',        #以下为原始代码所依赖的文件
                                     'BlowFish.cpp',
                                     'CyFile.cpp',
                                     'CyHash.cpp',
                                     'Encrypt.cpp',
                                     'EncryptTool.cpp',
                                     'md5.cpp',
                                     'sha1.cpp',
                                     'stdafx.cpp'
                                    ],
                          )
    
    setup(name = 'EncryptTool',    #打包后的名称
            version = '0.1',
            author = 'SWIG Docs',
            description = 'Simple swig pht from docs',
            ext_modules = [pht_module], #与上面的扩展模块名称一致
            py_modules = ['EncryptTool'], #需要打包的模块列表
        )

    编写完成后执行以下命令进行编译:

    python setup.py build

    编译通过后在build/lib.*开头的子目录下即可见到编译好的Python库文件:_EncryptTool.so和EncryptTool.py

    5 在Python加载库

    通过以下方式调用所生成的动态链接库即可:

    import EncryptTool
    EncryptTool.EncryptFile( "data.xml" , "data.pyblf" )     #加密
    EncryptTool.DecryptFile( "data.pyblf" , "data.pyxml" )    #解密
  • 相关阅读:
    art.dialog
    Asp.net中web.config配置文件详解
    Web.Config文件配置之限制上传文件大小和时间
    Asp.net中的一个判断session是否合法的做法
    js倒计时
    Asp.net中web.config配置文件详解
    C#调用耗时函数时显示进度条浅探
    ChannelFactory
    NetTcpBinding 类nettcpbinding的属性和方法
    n!的位数 斯特林公式
  • 原文地址:https://www.cnblogs.com/Glucklichste/p/10982921.html
Copyright © 2011-2022 走看看