一.提取擴展函數的參數PyArg_ParseTuple()
int PyArg_ParseTuple(PyObject *arg, const char *format, ...);
參數 arg必須是一個元組對象,包含了Python傳遞給C函數的參數列表.
format 參數必須是一個字符串. format參數具體請查看:https://docs.python.org/zh-cn/3.7/c-api/arg.html#arg-parsing
剩餘參數是各個變量的地址,類型要與格式字符串對應。
例子:
static PyObject *LG_add(PyObject * self, PyObject *args){
int a,b;
if (!PyArg_ParseTuple(args,"ii",&a,&b)) { //將args 轉爲C int, 並放入 a,b 中.
return NULL;
}
...
}
int ok;
int i, j;
long k, l;
const char *s;
Py_ssize_t size;
ok = PyArg_ParseTuple(args, "s", &s); /* A string */
/* Possible Python call: f('whoops!') */
ok = PyArg_ParseTuple(args, "lls", &k, &l, &s); /* Two longs and a string */
/* Possible Python call: f(1, 2, 'three')*/
ok = PyArg_ParseTuple(args, "(ii)s#", &i, &j, &s, &size);
/* A pair of ints and a string, whose size is also returned */
/* Possible Python call: f((1, 2), 'three') */
{
const char *file;
const char *mode = "r";
int bufsize = 0;
ok = PyArg_ParseTuple(args, "s|si", &file, &mode, &bufsize);
/* A string, and optionally another string and an integer */
/* Possible Python calls:
f('spam')
f('spam', 'w')
f('spam', 'wb', 100000) */
}
{
int left, top, right, bottom, h, v;
ok = PyArg_ParseTuple(args, "((ii)(ii))(ii)",
&left, &top, &right, &bottom, &h, &v);
/* A rectangle and a point */
/* Possible Python call:
f(((0, 0), (400, 300)), (10, 10)) */
}
{
Py_complex c;
ok = PyArg_ParseTuple(args, "D:myfunction", &c);
/* a complex, also providing a function name for errors */
/* Possible Python call: myfunction(1+2j) */
}
注意任何由調用者提供的Python對象引用是 借來的 引用;不要遞減它們的引用計數!
二. 構造任意值 Py_BuildValue()
PyObject *Py_BuildValue(const char *format, ...);
接受一個格式字符串,與 PyArg_ParseTuple()
相同,但是參數必須是原變量的地址指針(輸入給函數,而非輸出).最終返回一個Python對象適合於返回C函數調用給Python代碼。
例子, 左邊是函數, 右邊是輸出.
Py_BuildValue("") None
Py_BuildValue("i", 123) 123
Py_BuildValue("iii", 123, 456, 789) (123, 456, 789)
Py_BuildValue("s", "hello") 'hello'
Py_BuildValue("y", "hello") b'hello'
Py_BuildValue("ss", "hello", "world") ('hello', 'world')
Py_BuildValue("s#", "hello", 4) 'hell'
Py_BuildValue("y#", "hello", 4) b'hell'
Py_BuildValue("()") ()
Py_BuildValue("(i)", 123) (123,)
Py_BuildValue("(ii)", 123, 456) (123, 456)
Py_BuildValue("(i,i)", 123, 456) (123, 456)
Py_BuildValue("[i,i]", 123, 456) [123, 456]
Py_BuildValue("{s:i,s:i}", "abc", 123, "def", 456) {'abc': 123, 'def': 456}
Py_BuildValue("((ii)(ii)) (ii)", (1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))
三. 解析參數並構建值變量 也就是之前的format參數
s (str) [const char *]
將一個Unicode對象轉換成一個指向字符串的C指針
3.2 數字
b (int) [unsigned char]
將一個非負的Python整型轉化成一個無符號的微整型,存儲在一個C unsigned char
類型中。
B (int) [unsigned char]
將一個Python整型轉化成一個微整型並不檢查溢出問題,存儲在一個C unsigned char
類型中。
h (int) [short int]
將一個Python整型轉化成一個C short int
短整型。
H (int) [unsigned short int]
將一個Python整型轉化成一個C unsigned short int
無符號短整型,並不檢查溢出問題。
i (int) [int]
將一個Python整型轉化成一個C int
整型。
I (int) [unsigned int]
將一個Python整型轉化成一個C unsigned int
無符號整型,並不檢查溢出問題。
l (int) [long int]
將一個Python整型轉化成一個C long int
長整型。
k (int) [unsigned long]
將一個Python整型轉化成一個C unsigned long int
無符號長整型,並不檢查溢出問題。
L (int) [long long]
將一個Python整型轉化成一個C long long
長長整型。
K (int) [unsigned long long]
將一個Python整型轉化成一個C unsigned long long
無符號長長整型,並不檢查溢出問題。
n (int) [Py_ssize_t]
將一個Python整型轉化成一個C Py_ssize_t
Python元大小類型。
c (bytes 或者 bytearray 長度爲1) [char]
將一個Python字節類型,如一個長度爲1的 bytes
或者 bytearray
對象,轉化成一個C char
字符類型。
在 3.3 版更改: 允許 bytearray
類型的對象。
C (str 長度爲1) [int]
將一個Python字符,如一個長度爲1的 str
字符串對象,轉化成一個C int
整型類型。
f (float) [float]
將一個Python浮點數轉化成一個C float
浮點數。
d (float) [double]
將一個Python浮點數轉化成一個C double
雙精度浮點數。
D (complex) [Py_complex]
將一個Python複數類型轉化成一個C Py_complex
Python複數類型。
3.3 其他對象
O (object) [PyObject *]
用一個C的對象指針存儲一個Python對象(沒有任何格式轉換)。這樣傳遞給C程序的是實際的對象。這個對象的引用計數不會增加。這個指針存儲的不是 NULL。
O! (object) [typeobject, PyObject *]
將一個Python對象存入一個C指針。和 O
類似,但是需要兩個C參數:第一個是Python類型對象的地址,第二個是存儲對象指針的C變量( PyObject*
變量)的地址。如果Python對象類型不對,會拋出 TypeError
異常。
O& (object) [converter, anything]
通過一個 converter 函數將一個Python對象轉換成一個C變量。這需要兩個參數:第一個是一個函數,第二個是一個C變量的地址(任意類型的),轉化爲 void *
類型。converter 函數像這樣被調用:
status = converter(object, address);
p (bool) [int]
測試傳入的值是否爲真(一個布爾判斷)並且將結果轉化爲相對應的C true/false整型值。如果表達式爲真置``1``,假則置``0``。它接受任何合法的Python值。參見 邏輯值檢測 獲取更多關於Python如何測試值爲真的信息。
(items) (tuple) [matching-items]
對象必須是Python序列,它的長度是 items 中格式單元的數量。C參數必須對應 items 中每一個獨立的格式單元。序列中的格式單元可能有嵌套。