Передача аргумента в модуле Python, написанном на C

У меня были проблемы с написанием модулей Python на C. Я начал с простого примера вычисления нормы двух точек. Код выглядит так,

_norm.c

#include <Python.h>
#include "norm.h"

static char module_docstring[] =
    "This module provides an interface for computing the norm using C.";
static char norm_docstring[] =
    "Calculate the norm between two points";
static char norm2_docstring[] =
    "Calculate the square norm between two points. For efficiency.";

static PyObject *norm_norm(PyObject *self, PyObject *args);

static PyObject *norm_norm2(PyObject *self, PyObject *args);

static PyMethodDef module_methods[] = {
    {"norm", norm_norm, METH_VARARGS, norm_docstring},
    {"norm2", norm_norm2, METH_VARARGS, norm2_docstring},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC init_norm(void) {
    PyObject *m = Py_InitModule3("_norm", module_methods, module_docstring);
    if (m == NULL)
        return;
}

static PyObject *norm_norm(PyObject *self, PyObject *args) {
   double x1, y1, x2, y2;
   /* Parse the input tuple */
   if (!PyArg_ParseTuple(args, "ddOOO", &x1, &y1, &x2, &y2))
       return NULL;

/* Call the external C function to compute the norm. */
double value = norm(x1, y1, x2, y2);

if (value < 0.0) {
    PyErr_SetString(PyExc_RuntimeError,
                    "Norm returned an impossible value.");
}
PyObject *ret = Py_BuildValue("d", value);
return ret;
}

норма.с

#include <math.h>

long double norm2(long double x1, long double y1, long double x2, long double y2) {
    long double xd = x2 - x1;
    long double yd = y2 - y1;
    return xd * xd + yd * yd;
}

long double norm(long double x1, long double y1, long double x2, long double y2) {
    return sqrt(norm2(x1, y1, x2, y2));
}

setup.py

from distutils.core import setup, Extension

setup(
    ext_modules=[Extension("_norm", ["_norm.c", "norm.c"])]
)

Я собираю пакет следующим образом:

python setup.py build_ext --inplace

И компилируется без проблем. Однако, когда я пытаюсь использовать его, я получаю сообщение об ошибке о количестве аргументов.

>>> import _norm
>>> _norm.norm(1,2,5,6)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: function takes exactly 5 arguments (4 given)

Я предполагаю, что это может иметь какое-то отношение к объявлению PyObject *norm_norm(), поскольку оно передается *self, но я не уверен, должно ли это влиять на аргументы, которые я передаю модулю на стороне Python. вещи. Буду признателен за любую помощь/предложения.


person Dex    schedule 09.07.2014    source источник


Ответы (1)


Проблема в строке формата PyArg_ParseTuple. Вы пытаетесь извлечь четыре двойных аргумента, но строка формата предназначена для двух двойных аргументов и трех произвольных объектов Python ("ddOOO").

Правильная строка формата должна быть «dddd» для того, что вы пытаетесь сделать. Изменить это

если (!PyArg_ParseTuple(аргументы, "ddOOO", &x1, &y1, &x2, &y2))

с

если (!PyArg_ParseTuple(аргументы, "dddd", &x1, &y1, &x2, &y2))

person sterin    schedule 11.07.2014