在python中使用c語言編寫的庫


本文使用的 cffi 官網網址:https://cffi.readthedocs.io/en/latest/overview.html

cffi 自己本身使用了pycparser 這個庫,是用python編寫的c語言parser庫,官網地址: https://github.com/eliben/pycparser

 

 

python被稱為是“膠水語言”,號稱能夠“方便地”調用其他語言,比如c。但是實際操作中,對於非碼農出身的人來說寫語言接口還是很痛苦的事情。(我就從來沒有試圖去寫過ctype或者swig之類的高級貨,一眼看去完全被嚇到。)最近發現了一個python模塊,“C Foreign Function Interface for Python”(cffi),它把很多低層次的接口都隱藏起來,用戶從而不需要寫那些讓人抓狂的接口文件也能非常方便的調用C語言了。(另外一種方便調用C語言的辦法是使用Cython],我有時間會在另一篇文章介紹。)

假設我有一個寫好的C語言函數,定義在GSL(GNU Scientific Library)里面的Bessel函數。

// foo.c
#include <gsl/gsl_sf_bessel.h>

double foo(double a, double b){ return gsl_sf_bessel_J0(a + b); } 

接下來,我們想在python中用cffi模塊調用這個用C語言定義的函數foo的“簽名”,即輸入和輸出的數據類型。

# demo_1.py
from cffi import FFI ffi = FFI() ffi.cdef("double foo(double, double);") 

下一步,我們要把函數foo.c這個源文件直接傳遞python 2. 把

# demo_1.py (cont.)
import os file_dir = os.path.abspath('.') lib = ffi.verify("#include <foo.c>", include_dirs=[file_dir], libraries=['gsl', 'gslcblas']) 

foo的定義的。它的用法是,用一個string直接告訴python,我要載入foo定義的C語言源文件。參數foo.c所在的位置。因為我把foo.c放在了同一個文件家里,所以我可以用foo.c的文件夾地址。最后,參數foo調用了GSL庫里面的Bessel函數。 這樣就搞定了,我們可以在python中直接調用C語言定義的函數

# demo_1.py (cont.)
a, b = 1.2, 3.4 print lib.foo(a, b) 

之前說到第二種傳遞函數foo和其他用到的庫文件比如GSL“打包”成一個新的庫文件,比如叫libfoo.so而無需再指定其他庫文件了。具體方法如下:

注意在這一步中我們把gsl和gslclbas這兩個庫文件“打包”進了libfoo.so了。

 

# demo_2.py
from cffi import FFI ffi = FFI() ffi.cdef("double foo(double, double);") import os file_dir = os.path.abspath('.') lib = ffi.verify("#include <foo.c>", include_dirs=[dir], library_dirs=[dir], libraries=['foo']) a, b = 1.2, 3.4 print lib.foo(a, b) 

注意觀察library_dirs用來說明庫文件libfoo.so經常不在系統默認的gsl等庫文件確實一般安裝在libraray_dirs這個參數來指明)。 2. 參數[foo],而不是gsllibfoo.so里面。

最后,假如函數foo.h來包含

// foo.h
#ifndef foo_h__ #define foo_h__ double foo(double, double); #endif 

然后把該頭文件傳遞過去就可以了,即

, include_dirs=[dir], library_dirs=[dir], libraries=['foo'])
配置CFFI接口,參考https://cffi.readthedocs.org/en/latest/installation.html





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM