python使用cffi模塊調用c函數
一、cffi簡介
Cffi是python調用c函數的接口。幾乎所有c和pythond的交互都是基於類似於c的聲明一樣,因此可以直接複製粘貼c的頭文件或者文檔使用。
Cffi接口遵循如下的原則:
1、目標是在不需要了解第三方語言(cython、swig、ctypes)的基礎上在python中調用c庫函數;cffi的設計只需要用戶瞭解c和python,最大限度的減少用戶學習額外的api;
2、保存原有python的邏輯不需要寫太多的c代碼;從python代碼頭部的cdef聲明中調用c編譯器去驗證和連接到c數據結構及函數;
3、越來越完善;到現在爲止c99並不是全部支持,但是c89應該全部支持了,包含一些宏定義;
4、嘗試去支持cpython和pypy;
5、此項目不是在python中嵌入可執行c代碼,而是關於如何在python中調用已存在的c庫函數;
6、不支持c++
二、相關api的使用
參考官方文檔:
https://cffi.readthedocs.io/en/release-1.12/ref.html
三、加載並調用C基本類型
基本類型包括 int、 char、unsigned int、unsigned char、 char[]、int[]、int*、char **…
x = ffi.new(“char[]”, “hello”)
print len(x),x[0],ffi.string(x)
輸出 6 h hello
array = ffi.new(“int[]”, [1, 2, 3, 4])
相當於int array[] = { 1, 2, 3, 4 };
x = ffi.new(“int *”)
x[0] = 42
print x[0]
輸出 42
轉換指針類型
stu = ffi.new(‘struct stu*’)
stu_ptr = ffi.cast(“char *”, stu)
三、使用筆記
import cffi
import setproctitle
#實例化ffi
ffi=cffi.FFI()
#此處可以寫宏定義、結構體、函數聲明、全局變量等;
ffi.cdef("""
#define MAX_CLASS 10
#define MAX_COUNT 20
typef struct {
int age;
char sex;
float high;
}student;
int count_student();#函數聲明
int get_specical_stu(void *()(int id))
""")
#加載so庫(會自動搜索系統路徑),如果so庫之間有相互依賴關係,則使用ffi.RTLD_LAZY|ffi.RTLD_GLOBAL模式加載
liba=ffi.dlopen("liba.so",ffi.RTLD_LAZY|ffi.RTLD_GLOBAL)
libb=ffi.dlopen("libb.so",ffi.RTLD_GLOBAL)
#函數調用
liba.count_student()
#將python函數作爲回調函數註冊到c函數中
c_handle_test=ffi.new_handle(python_func) #結合ffi.from_handle使用
libb.get_special(c_handle_test)
#創建c類型的對象並初始化
c_stu_struct=ffi.new("student",[25,1,176])
#進程起別名
setproctitle.setproctitle("test_name")
參考文章:
官方文檔:https://cffi.readthedocs.io/en/release-1.12/ref.html
使用實例:http://wiki.jikexueyuan.com/project/openresty/lua/FFI.html
使用實例:https://blog.csdn.net/itisyang/article/details/54426631