C 擴展python,細節

一.提取擴展函數的參數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 中每一個獨立的格式單元。序列中的格式單元可能有嵌套。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章