這是一篇《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 擴充套件模組 單獨安裝...