使用C寫Python的模組

2021-07-14 15:54:02 字數 3112 閱讀 2562

概述

引入 python.h 標頭檔案

編寫包裝函式

處理從 python 傳入的引數

實現邏輯功能

處理 c 中的返回值

註冊函式

註冊模組

編譯原文發於2023年11月。

python 可以非常方便地和 c 進行相互的呼叫。

一般,我們不會使用 c 去直接編寫乙個 python 的模組。通常的情景是,我們需要把 c 的相關模組包裝一下,然後在 python 中可以直接呼叫它。或者是,把 python 邏輯中的某一效率要求很高的部分使用 c 來實現。整個過程大概是:

引入 python.h 標頭檔案。

編寫包裝函式。

函式中處理從 python 傳入的引數。

實現功能邏輯。

處理 c 中的返回值,包裝成 python 物件。

在乙個 pymethoddef 結構體中註冊需要的函式。

在乙個初始化方法中註冊模組名。

把這個 c 原始檔編譯成鏈結庫。

int

add(

intx

,inty)

//int main(void)

#include

static

pyobject

*w_add

(pyobject

*self

,pyobject

*args

)else

}static

pymethoddef

extendmethods

=,,};

pymodinit_func

initdemo

()

這個檔案一般位於 python 的主目錄中。比如我的 ubuntu 10.04 下,它的位置在:

/usr/

include

/python2

.6

在最後編譯的時候指定目錄就可以了。

因為 python 用到的函式與普通的 c 函式,在輸入和輸出上,會有一些不同,所以,我們需要把普通的 c 做一些封來給 python 用。

從另一方面來說,在實現功能的過程中,我們可以先完全不考慮這東西是拿給 python 用的,只專注於使用 c 把它寫好就可以了。最後,功能寫好,測試沒有問題之後,再做 python 封裝的工作。

包裝函式一般宣告成 static ,並且第乙個引數是乙個預設傳入的 python 物件,就是 python 中某個物件的屬性方法一樣,第二個引數才是我們呼叫時傳入的引數(實際上它是乙個序列化後的字串):

static

pyobject

*w_add

(pyobject

*self

,pyobject

*args

);

因為我們的相關函式,之後是在 python 環境中被呼叫的,那麼它顯然接受的就是從 python 環境下傳入的引數。這和 c 中你看到的函式是不同的,在 python 的世界中,一切都是物件。所以,包裝函式中首先要處理的問題就是解析從 python 佔獲取的引數。

常用的函式有: pyarg_parsetuple

intx;

inty

;pyarg_parsetuple

(args

,"i|i",&

x,&y

);

pyarg_parsetuple 的作用是解析我們從 python 中傳入的 args 這個字串,然後以我們規定的格式將解析結果放入指定變數的記憶體位。

" i|i " 就表示要把傳入的東西解析成兩個整數,同樣,還有 s 表示字串等。

這部分沒什麼特別的,只需要在 c 中一樣呼叫函式就可以了,相關變數我們已經在上一步處理過了。

add(x

,y);

我們使用 c 完成了功能邏輯, c 中會產生乙個返回值,要將這個值返回到我們之前呼叫函式的 python 環境中,當然還需要經過一些處理才行。

常用的函式是: py_buildvalue 。

return

py_buildvalue

("i"

,add(x

,y));

這個函式的用法和上一步中的 pyarg_parsetuple 是一樣的,它們過程相反。 py_buildvalue 把 c 中的值按給定的格式格式化成 python 需要的物件。這裡注意一下,對於 w_add 這個函式,我們可是宣告了它的返回型別為 pyobject* 的哦。

在上面的實現完成之後,就需要作匯出的準備了。第一步,就是要在乙個型別為 pymethoddef 的結構體中註冊我們需要匯出到 python 中的函式:

static

pymethoddef

extendmethods

=,,}

這個結構體成員有四個函式:

" add " 匯出後在 pyhton 中可見的方法名。

w_add 實際對映到 c 中的方法名。

此方法的注釋。

在註冊了方法後,就要註冊此模組了。方法是定義乙個 init* 的函式:

pymodinit_func

initdemo

()

方法名必須是 init 加上模組名,然後呼叫 py_initmodule 來註冊模組,這個函式的第乙個引數就是模組名,第二個引數是此模組中我們匯出的方法,就是上一步我們定義的結構體。

最後一步就是編譯了。沒什麼特別的,指定好 python.h 標頭檔案的位置就可以了:

gcc demo.c 

-i /usr

/include

/python2.6

-shared

-o demo

.so

當然,鏈結庫的名字要和我們期望匯出的模組名一致。

這樣,你就可以在 python 中使用 import 直接引入 demo 模組,然後呼叫它的 add 方法了:

import

demo

demo

.add(3

,4)

c寫python庫 c寫python模組擴充套件

結構 xorcrypt 0.2 setup.py xorcrypt2.c readme setup.py usr bin python from distutils.core import setup,extension version 0.2 macros module version s ver...

python使用argparse模組寫命令列內容

寫命令python和c是有很大區別的。c可以通過mian函式,而python可以通過呼叫內建模組。import argparse parse argparse.argumentparser parse.add argument bug feature help file that only cont...

Python學習 測試和使用自己寫的模組

首先我們先自己寫乙個模組,並且可以執行當前檔案時測試該模組是否正常。usr bin env python3 coding utf 8 a test module author csdn author deftest1 print hello,test1 deftest2 print hello,te...