19

我一直在尝试学习如何为 Python 编写 C 扩展,并希望确保我了解 PyArg_ParseTupleAndKeywords 的工作原理。

我相信第一个参数是一个 PyObject 指针,它指向按传递顺序传递给 C 扩展函数的参数数组。第二个参数是传递的关键字列表,它们传递的位置,很可能是某种指示标志,告诉关键字从哪个位置开始,位置变得无关紧要。

然后 PyArg_ParseTupleAndKeywords 使用其关键字列表(第 4 个参数)在用关键字指定的参数与格式字符串(第 3 个参数)和 C 变量的地址(第 5 个和 + 参数)之间进行映射,适当的值应复制到该地址。

我的理解正确吗?当我阅读在线文档时,我看到的只是对“位置参数和关键字参数”的引用,这让我感觉有点摸不着头脑。处理 PyArg_ParseTupleAndKeywords 的 Python 解释器的文件在哪里?

4

2 回答 2

16

在 python 中模拟以下内容:

def keywords(a, b, foo=None, bar=None, baz=None):
    pass

以下将起作用:

static PyObject *keywords(PyObject *self, PyObject *args, PyObject *kwargs)
{
    char *a;
    char *b;
    char *foo = NULL;
    char *bar = NULL;
    char *baz = NULL;

    // Note how "a" and "b" are included in this
    // even though they aren't supposed to be in kwargs like in python
    static char *kwlist[] = {"a", "b", "foo", "bar", "baz", NULL};

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|sss", kwlist, 
                                     &a, &b, &foo, &bar, &baz)) 
    {
        return NULL;
    }

    printf("a is %s\n", a);
    printf("b is %s\n", b);
    printf("foo is %s\n", foo);
    printf("bar is %s\n", bar);
    printf("baz is %s\n", baz);

    Py_RETURN_NONE;
}

// ...

static PyMethodDef SpamMethods[] = 
{
    // ...
    {"keywords", (PyCFunction) keywords, METH_VARARGS | METH_KEYWORDS, "practice kwargs"},
    {NULL, NULL, 0, NULL}
    // ...
}

并使用它:

from spam import keywords

keywords()         # Fails, require a and b
keywords('a')      # fails, requires b
keywords('a', 'b')
keywords('a', 'b', foo='foo', bar='bar', baz='baz') 
keywords('a', 'b','foo', 'bar', 'baz')
keywords(a='a', b='b', foo='foo', bar='bar', baz='baz')
于 2017-02-12T21:19:07.787 回答
8

您是否阅读了http://docs.python.org/c-api/arg.html上的开场解释?它很好地解释了正在发生的事情。不要直接参考PyArg_ParseTupleAndKeywords; 它假设您阅读了上面的文字,并且它本身并不是很有帮助。

不过,你几乎得到了它。第一个参数确实是传入位置参数的列表。第二个是传入关键字参数的映射(将给定关键字名称映射到给定值)。第四个参数实际上是您的函数准备接受的关键字列表。是的,第 3 个参数是格式字符串,第 5 个和以后的参数是 C 指针,值被复制到其中。

您会PyArg_ParseTupleAndKeywords()Python/getargs.c.

于 2012-05-16T20:12:01.403 回答