zoukankan      html  css  js  c++  java
  • python如何调用c编译好可执行程序

    python如何调用c编译好可执行程序
     
       

    以下总结出几种在Python 中调用 C/C++ 代码的方法

    --------------------------------------------------------------------

    发现做便捷的是使用popen

    from os import popen

    popen('/home/pengyan/Downloads/VIC/sanxia/vicNl -g /home/pengyan/Downloads/VIC/sanxia/xings_global')

    popen('/home/pengyan/Downloads/VIC/sanxia/rout /home/pengyan/Downloads/VIC/sanxia/xings_rout')

    ?? 目前还不会用python 切换文件目录

    可以采用绝对路径,但是好像绝对路径时,计算速度变慢

    -------------------------------------------------------------------

      使用ctypes 模块调用 C 动态库

      从Python2.5 开始, Python 开始提供 ctypes 模块来提供对 C 语言编译的动态库文件的调用。注意,  这里特指C 的动态库 ,用C++ 编译的动态库 ctypes 虽然能够加载,但调用时的函数名已经由于 C++ 的重载特性被加以修改,难以调用。 使用 ctypes 调用 C 动态库的好处在于不用进行额外的开发,可以直接使用编译好的动态库。 ctypes 提供了完整的 C 类型封装,也支持自定义类型,大大减少在调用过程中的工作量。 ctypes 的使用很简单,只需熟悉 python 封装与 C 中的对应关系即可。以下用一个简单的例子来说明:

      from  ctypes  import  * #导入ctypes模块

      libc = cdll.LoadLibrary("libc.so.6") #加载libc动态库

      str  = c_char_p(' Hello World! ') #使用char *在ctypes中的对应封装c_char_p,相当于char* str=”Hello World!”

      libc.printf(“yell: %s ”,  str ) #调用printf函数

      ctypes的功能当然远不止这些,有兴趣的同学可以参考这里 http://docs.python.org/library/ctypes.html

      使用Python 的扩展( Extending )机制

      ctypes很方便地可以调用 C 的动态库,但是对 C++ 编译的动态库,调用起来很困难。这种情况利用 Python 的 Extending 机制就可以解决。 Python 提供了一套完整的框架来使用 C/C++ 编写扩展库,可以很灵活的开发 C++ 扩展模块。这种方法的缺点是工作量比较大,需要为每一个方法编写接口,这里不做详细介绍,可以参考: http://docs.python.org/extending/extending.html#writing-extensions-in-c

      那么有什么办法可以高效的调用C++ 动态库呢,答案是 SWIG 。

      使用SWIG 生成扩展模块

      上面提到了Python 的扩展机制,缺点是工作量比较大,这里介绍一个工具 SWIG 。 SWIG 是一种简化脚本语言与 C/C++ 接口的开发工具,通过包装和编译 C 语言程序来达到与脚本语言通讯目的的工具。它正是基于 Python 的扩展机制,自动生成接口文件,再编译成可以被 Python 调用的动态库扩展模块。

      使用SWIG 生成扩展模块分为以下几步:

    1. 将需要调用的代码编译成目标文件(.o) ;
    2. 用SWIG 读取编写描述文件 (.i) ,生成接口文件 (.cxx) ;
    3. 将接口文件编译为目标文件(.o) ;
    4. 将接口文件的目标文件和原代码段的目标文件一起编译成动态库 ;

    假设有如下文件

      swig_ex.cpp 需要转换成扩展库的原始代码,包含一个int fact(int) 函数

      swig_ex.h  原始代码的头文件

      swig_ex.i SWIG描述文件

      swig_ex.i是一个描述文件,有 SWIG 自己的语法,比较简单,内容如下:

    %module swig_ex
    %{
        #define SWIG_FILE_WITH_INIT
        #include "swig_ex.h"
    %}
    int fact(int n);

      再写一个Makefile 来把这些文件编译成动态库 :

    all: swig_ex.o swig_ex_wrap.o _swig_ex.so
    swig_ex.o: swig_ex.cpp swig_ex.h #编译源文件
       g++ -fPIC -c swig_ex.cpp
    swig_ex_wrap.o: swig_ex.i swig_ex.o #根据 SWIG 描述文件 (.i) 生成接口文件 (.cxx) ,再编译之
       swig -c++ -python swig_ex.i
       g++ -O2 -fPIC -c swig_ex_wrap.cxx -I/home/work/linyi/autoframe/tool/python/include/python2.6/
    _swig_ex.so: swig_ex_wrap.o #将目标文件打包成动态库
       g++ -shared swig_ex.o swig_ex_wrap.o -o _swig_ex.so
    .PHONY: clean
    clean:
       rm -rf swig_ex_wrap.* swig_ex.py _swig_ex.so

      编译好以后会有一个so 和 py 文件,写一个 setup.py 把他们安装到 python 目录就可以和其他模块一样被 python 调用了:

    Import swig_ex
    swig_ex.fact(10)

      参考文档地址:http://www.swig.org/Doc1.3/SWIGDocumentation.html

      原始但有效的方法

      除了上面这些方法,在Python 中借用 C/C++ 代码最原始有效的方法就是将代码编译成可执行程序,从 Python 里用 Popen 方法来调用获取输出。这种方法简单有效,缺点是不够灵活,有比较大的局限性,不过在很多情况下也已经足够了。

    pipe = os.popen('./tool –a %s –b %s' % (“hello”, “world”))
    re = pipe.read()

      其他方法

      以上这些方法基本上已经能满足Python 调用 C/C++ 的需求了,此外还有一些方法,例如使用 Boost.Python ,使用 Pyrex ,这些方法都能提供 Python 与 C/C++ 的交互。

      总结

      在Python 中引用 C/C++ 模块的方法较多,根据需要从中选择恰当的方法可以减少很多工作量。

      在Python 中引用 C/C++ 模块弥补了 Python 脚本测试框架的很多不足,在提高代码复用率的同时,模块的性能也大大提高。

  • 相关阅读:
    pandas Dataframe filter
    process xlsx with pandas
    data manipulate in excel with easyExcel class
    modify registry in user environment
    add number line in vim
    java import webservice
    ctypes MessageBoxA
    music 163 lyrics
    【python实例】自动贩卖机
    【python基础】sys模块(库)方法汇总
  • 原文地址:https://www.cnblogs.com/L-H-R-X-hehe/p/3817438.html
Copyright © 2011-2022 走看看