一.提取扩展函数的参数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 中每一个独立的格式单元。序列中的格式单元可能有嵌套。