PYCFunctionWithKeywords неправильно вызывается из python

Я пытаюсь написать модуль C-расширения для python3, скажем, foo, и я пытаюсь определить метод, который может принимать аргументы ключевого слова.

static PyObject* fooImpl(PyObject*, PyObject*, PyObject*);
static PyObject* fooImpl2(PyObject, PyObject*);
static PyMethodDef fooMethods[] = {
    {"foo_impl", (PyCFunction) fooImpl, METH_VARARGS | METH_KEYWORDS, "Some description"},
    {"foo_impl2", fooImpl2, METH_VARARGS, "Some description"},
    {NULL, NULL, 0, NULL}
};

PyObject* fooImpl(PyObject* self, PyObject* args, PyObject* kwds) {
    static const char *keywordList[] = { "kw1", "kw2", NULL};
    PyObject *input = nullptr;
    PyObject *kw1Val = nullptr;
    PyObject *kw2Val = nullptr;
    PyObject *returnVal = nullptr;
    int err = PyArg_ParseTupleAndKeywords(args, kwds, "O|OO",
                                          const_cast<char**>(keywordList),
                                          &input, &kw1Val, &kw2Val);
    if (!err) {
       return NULL;
    }
    //// Do something with args to compute returnVal
    return returnVal;
}

Когда я пытаюсь это сделать в python, я получаю следующую ошибку

>>> import foo as fp
>>> arg1 = ...
>>> arg2 = ...
>>> arg3 = ...
>>> a = fp.foo_impl(arg1, kw1 = arg2, kw2 = arg3);
TypeError: function takes at most 2 arguments (3 given)

Похоже, интерпретатор не регистрирует флаг METH_KEYWORDS в PyMethodDef . Есть ли другой способ добавить методы PyCFunctionWithKeywords в C-расширение в Python3. Единственный источник, который я нашел, был этот пост о стеке, восходящий к документации Python здесь

Любая помощь приветствуется


person Mahesh Ravishankar    schedule 06.01.2016    source источник


Ответы (1)


Вы не определили все ключевые слова. Даже если аргумент не является необязательным, ему все равно необходимо определить имя, чтобы его можно было передать по ключевому слову или позиционно (и поэтому PyArg_ParseTupleAndKeywords может сопоставлять позиции с ключевыми словами, если необязательные аргументы передаются позиционно). По сути, количество имен ключевых слов всегда должно соответствовать максимальному количеству аргументов для анализа.

Изменять:

static const char *keywordList[] = { "kw1", "kw2", NULL};

to:

static const char *keywordList[] = { "input", "kw1", "kw2", NULL};

Очевидно, вы можете назвать первый аргумент как угодно; Я просто сопоставил имя переменной C.

person ShadowRanger    schedule 07.01.2016
comment
Спасибо ShadowRanger. Я сам только что понял ответ, посмотрев код на Python. - person Mahesh Ravishankar; 07.01.2016