python c模組擴充套件及PyIntObj物件

2021-06-18 18:55:41 字數 2866 閱讀 8321

這是一篇《python原始碼剖析》的閱讀筆記。

原始碼位置:

python中一些模組是用c來實現的,所以我們也可以用c來實現一些自定義模組。在讀《python原始碼剖析》的過程中,使用一些自定義的模組可以很方便的了解其中一些原理,而不用每改一行**都得編譯整個python的原始碼。

用c實現自定義模組的流程是:

1. 封裝自定義方法

2. 匯出自定義方法

封裝函式的定義為:

pyobject * methodname(pyobject* self,  pyobject* args);
引數含義:

self, 類似有python類函式的self,這裡不管它

args, 輸入引數列表,它的實現我們暫時不管,了解如何從裡面取引數就行了:pyarg_parsetuple(args, "i|s",&x, &y),這意思就是,args中取出乙個整數給x,乙個字串給y。就這麼簡單,通常如下使用:

if (!pyarg_parsetuple(args, "i|s",&x, &y))

返回值:

乙個python物件,通常用:py_buildvalue來構建,例如return py_buildvalue("i", z),當然沒返回值的函式就是py_none了。至於i是什麼意思就不說了。

乙個加法封裝的示例:

pyobject * myadd(pyobject* self,  pyobject* args)

z = x + y;

returnpy_buildvalue("i", z);

}

主要步驟就是將所有自定義的方法組成乙個列表,然後匯出列表

1. 列**式:

static pymethoddef myaddmethods =

,

};

每一項的含義為:python中的方法名(add);對應的自定義的方法(myadd);meth_varargs表示c的呼叫方式,一般就寫這個了;這個函式的__doc__("add method")。以null結尾。

2. 匯出列表:

void initadd()

這裡要注意的是:函式名必須為inixx的形式,xx為模組名。py_initmodule的第乙個引數是模組名,第二個引數是模組函式列表。

小整數池的出現是為了解決頻繁申請銷毀int物件的問題。

在程式中,經常會使用一些不大的整數。想想c中的for迴圈,對於python來說,每次迴圈都要為i申請和銷毀乙個pyintobject結構體,這個消耗是比較大的。

小整數物件就是將一些較少的數的pyintobject先申請出來,池子的大小定義在intobject.c中的nsmallposints和nsmallnegints,在python2.7.5中,是257和5,也就是小整數的範圍是[-5, 256]。

大整數物件池是由一串pyintblock的鍊錶,每次申請的時候批量申請,也是一種優化方式。

讓我們來hack一下這個大小整數物件池。

1.      先在原始碼裡將nsmallposints和nsmallnegints匯出,更改原始碼object/intobject.c:

在該檔案中加入:

int small_pos_ints = nsmallposints;

int small_neg_ints = nsmallnegints;

2. 找到block_list定義的位置,去掉static,讓這個變數能在so中extern到,完成之後編譯python原始碼。

3. 因為python標頭檔案中沒有定義pyintblock,所以自己定義乙個:

struct _pyintblock ;

typedef struct _pyintblock pyintblock;

4. 實現wrap方法:

externint small_neg_ints;

extern int small_pos_ints;

//print the range of small ints

void printrange()

printf("small ints's range: -%d <=%d\n", small_neg_ints, small_pos_ints);}

extern pyintblock * block_list;

void printblockinfo()

printf("block_listsize: %d\n", count);

}

5. 封裝:

pyobject * wrap_printint(pyobject* self, pyobject* args)

6. 匯出就不寫了。

7. 將其編譯成hackint.so

執行結果:

這裡可以看到小整數池和大整數池的大小。

在看大整數物件時,曾經有個疑問,在python中:

a = 10000

b = 10000

pyobject * wrap_printaddr(pyobject* self,pyobject* args)

看到結果:

Python C語言擴充套件

這裡編寫個簡單例子來說明下具體是如何操作的 建立dll專案,結構如下 test mydll.h mydll.c 標頭檔案 mydll.h ifndef mydll h define mydll h ifdef build dll define dll export declspec dllexpor...

Python C擴充套件實踐 效能對比

因為效能等一些原因,希望用c來擴充套件python。有多種方法,例如 這裡闡述最後一種方式的實現。首先需要 include 需要實現下面三個函式 static pyobject funcname pyobject self,pyobject args 函式定義 static pymethoddef ...

python及拓展版 python擴充套件模組

一 擴充套件模組 影像擴充套件模組 pil 單獨安裝 影像擴充套件模組需 安裝pil v1.16 與python 版本對應 安裝完畢後呼叫方式為 import image 注意首字母大寫!注意路徑字串的處理 row,col im.size 獲取影像的尺寸 聲音引擎 pytts 擴充套件模組 單獨安裝...