PyArg_ParseTuple函数文档

原版来源Python与其他语言结合的参数转换函数PyArg_ParseTuple()

注:手动机翻,对不恰当地方进行过调整,仍有待改进地方。

官方手册

最后修改日期2018-9-28



PyArg_ParseTuple()函数的定义:

int PyArg_ParseTuple(PyObject *arg, char *format, ...);

arg参数必须是一个元组对象,它包含了从Python传递到C语言函数的参数列表。format参数必须是格式字符串, 具体将在下方解释.其余参数必须是变量的地址,其类型由格式字符串决定。为了能成功的转换,arg对象必须与格式匹配,并且前后一一对应。

注意,虽然 PyArg_ParseTuple() 检查Python是否具有所需类型, 但是它不能检查传递给调用的C变量地址的有效性: 如果在那里出错,您的代码可能会崩溃,或者覆盖内存中的随机位置。所以要小心!

格式字符串由零或多个“格式单元”组成. 格式单元描述了一个Python对象; 它通常是单个字符或格式单元的插入序列. 除了少数例外,非括号序列的格式单元通常对应于PyArg_ParseTuple()的单个地址参数. 在以下描述中,引用的表单是格式单元;圆括号中的描述是与格式单元匹配的Python对象类型;方括号中的描述是应该传递其地址的C变量的类型。(使用“&”运算符传递变量的地址。)

注意,提供给调用者的任何Python对象引用都是借来的引用;不要降低他们的引用计数!

"s" (string or Unicode object) [char *]

将Python字符串或Unicode对象转换为指向字符串的C指针。不能为字符串本身提供存储;指向现有字符串的指针存储在您传递地址的字符指针变量中。C字符串以NULL结尾。Python字符串不能包含嵌入的空字节;如果有,就会引发TypeError异常。使用默认编码将Unicode对象转换为C字符串。如果转换失败,就会引发一个UnicodeError异常。

"s#" (string,Unicode or any read buffer compatible object) [char *, int]

“s”上的这个变体存储在两个C变量中,第一个变量是指向字符串的指针,第二个变量是字符串的长度。在这种情况下,Python字符串可能包含嵌入的空字节。如果可能的话,Unicode对象会返回一个指向对象的默认编码字符串版本的指针。所有其他与读取缓冲区兼容的对象都将对原始内部数据表示的引用传回。

"z" (string or None) [char *]

与“s”类似,但是Python对象也可能是None,在这种情况下,C指针被设置为NULL

"z#" (string or None or any read buffer compatible object) [char *, int]

这是"s#"就像"z"是"s"一样。

"u" (Unicode object) [Py_UNICODE *]

将Python Unicode对象转换为指向16位Unicode (UTF-16)数据的空端缓冲区的C指针。与“s”一样,不需要为Unicode数据缓冲区提供存储;指向现有Unicode数据的指针被存储到Py_UNICODE指针变量中,您传递的地址就是这个变量。

"u#" (Unicode object) [Py_UNICODE *, int]

“u”上的这个变体存储在两个C变量中,第一个变量是指向Unicode数据缓冲区的指针,第二个变量是它的长度。

"es" (string,Unicode object or character buffer compatible object) [const char *encoding,char **buffer]

这个“s”的变体用于编码Unicode和转换为Unicode的对象到字符缓冲区。它只适用于不嵌入空字节的编码数据。

读取一个变体C变量C和商店为两个变量,第一个指针指向一个编码名称字符串(encoding),第二个一个指向指针的指针一个字符缓冲区(**buffer,缓冲用于存储编码数据)和第三个整数指针(*buffer_length,缓冲区长度)。

编码名称必须映射到已注册的编解码器。如果设置为NULL,则使用默认编码。

PyArg_ParseTuple()将使用PyMem_NEW()分配一个所需大小的缓冲区,将已编码的数据复制到这个缓冲区中,并调整*buffer以引用新分配的存储。调用方负责调用PyMem_Free()以在使用后释放分配的缓冲区。

"es#" (string,Unicode object or character buffer compatible object) [const char *encoding,char **buffer, int *buffer_length]

这个“s#”的变体用于编码Unicode和转换为Unicode的对象到字符缓冲区。它读取一个C变量并存储到两个C变量,第一个指针指向一个编码名称字符串(encoding),第二个一个指向指针的指针一个字符缓冲区(**buffer,缓冲用于存储编码数据)和第三个整数指针(*buffer_length,缓冲区长度)。

编码名称必须映射到已注册的编解码器。如果设置为NULL,则使用默认编码。

操作方式有两种:

如果*buffer指向空指针,PyArg_ParseTuple()将使用PyMem_NEW()分配一个所需大小的缓冲区,将已编码的数据复制到这个缓冲区,并调整*buffer以引用新分配的存储。调用方负责在使用后调用PyMem_Free()来释放分配的缓冲区。

如果*buffer指向非空指针(已经分配的缓冲区),PyArg_ParseTuple()将使用这个位置作为缓冲区,并将*buffer_length解释为缓冲区大小。然后,它将把编码后的数据复制到缓冲区中,并终止(0-terminate)它。缓冲区溢出以异常信号表示。

在这两种情况下,都将*buffer_length设置为编码数据的长度,没有后面的0字节(0-byte)

"b" (integer) [char]

将Python整数转换为存储在C语言char中的一个小int(tiny int)。

"h" (integer) [short int]

将Python整数转换为C语言short int。

"i" (integer) [int]

将Python整数转换为普通的C语言int。

"l" (integer) [long int]

将Python整数转换为C语言long int。

"c" (string of length 1) [char]

将长度为1的字符串表示的Python字符转换为C语言char。

"f" (float) [float]

将Python浮点数转换为C语言float。

"d" (float) [double]

将Python浮点数转换为C 语言double。

"D" (complex) [Py_complex]

将Python复数转换为C语言Py_complex结构。

"O" (object) [PyObject *]

在C对象指针中存储Python对象(不进行任何转换)。因此,C程序接收传递的实际对象。对象的引用计数没有增加。存储的指针不是空的(NULL)。

"O!" (object)[typeobject, PyObject *]

将Python对象存储在C对象指针中。这类似于“O”,但是接受两个C参数:第一个是Python类型对象的地址,第二个是对象指针存储在其中的C变量(类型为PyObject *)的地址。如果Python对象没有所需的类型,就会引发类型错误(TypeError)。

"O&" (object)[converter,anything]

通过转换器函数将Python对象转换为C变量。这需要两个参数:第一个是函数,第二个是C变量(任意类型)的地址,转换为void *。该转换器功能依次调用如下:

status = converter(object,address);

对象是要转换的Python对象,地址是传递给PyArg_ConvertTuple()的void *参数。对于成功的转换,返回的状态应该是1,如果转换失败,则返回0。当转换失败时,converter(函数名可能错误)函数应该引发异常。

"S" (string) [PyStringObject *]

与“O”类似,但要求Python对象是字符串对象。如果对象不是字符串对象,则引发类型错误(TypeError)。C变量也可以声明为PyObject *

"U" (Unicode string) [PyUnicodeObject *]

与“O”类似,但要求Python对象是Unicode对象。如果对象不是Unicode对象,则引发类型错误(TypeError)。C变量也可以声明为PyObject *

"t#" (read-only character buffer) [char *, int]

与“s#”类似,但接受任何实现只读缓冲区接口的对象。char *变量设置为指向缓冲区的第一个字节,int设置为缓冲区的长度。只接受单段缓冲对象;对所有其他类型都引发类型错误(TypeError)。

"w" (read-write character buffer) [char *]

类似于“s”,但接受任何实现读写缓冲区接口的对象。调用者必须通过其他方法确定缓冲区的长度,或者使用“w#”。只接受单段缓冲对象;对所有其他类型都引发类型错误(TypeError)。

"w#" (read-write character buffer) [char *, int]

与“s#”类似,但接受任何实现读写缓冲区接口的对象。char *变量设置为指向缓冲区的第一个字节,int设置为缓冲区的长度。只接受单段缓冲对象;对所有其他类型都引发类型错误(TypeError)。

"(items)" (tuple) [matching-items]

对象必须是一个Python序列,其长度是项中的格式单元数。C参数必须对应于项中的单个格式单元。序列的格式单元可以嵌套。

注意:在Python 1.5.2版本之前,这个格式说明符只接受包含单个参数的元组,而不是任意序列。以前导致在这里引发类型错误(TypeError)的代码现在可以毫无例外地继续进行。对于现有的代码来说,这并不是一个问题。

可以在请求整数的地方传递Python长整数;然而,没有进行适当的范围检查——当接收字段太小而无法接收值时,最重要的位将被无声地截断(实际上,语义是从C中的downcast继承来的——您的里程可能会有所不同(your mileage may vary))。

其他一些字符在格式字符串中有意义。这些可能不会发生在嵌套的括号中。它们是:

"|"

指示Python参数列表中的其余参数是可选的。与可选参数对应的C变量应该初始化为它们的默认值——当没有指定可选参数时,PyArg_ParseTuple()不会触及相应的C变量(variable(s))的内容。

":"

格式单元列表在此结束;冒号后面的字符串用作错误消息中的函数名(PyArg_ParseTuple()引发的异常的“关联值(associated value)”)。

";"

格式单元列表在此结束;冒号后面的字符串用作错误消息,而不是默认错误消息。显然,“:”和“;”相互排斥。

一些示例调用:

    int ok;

    int i, j;

    long k, l;

    char *s;

    int size;


    ok = PyArg_ParseTuple(args, "");/* No arguments */

        /* Python call: f() */


    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, whosesize is also returned */

        /* Possible Python call: f((1, 2),'three') */

    {

        char *file;

        char *mode = "r";

        int bufsize = 0;

        ok = PyArg_ParseTuple(args,"s|si", &file, &mode, &bufsize);

        /* A string, and optionally anotherstring 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 functionname for errors */

        /* Possible Python call:myfunction(1+2j) */

    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容