2012-07-20 4 views
1

Я делаю свое первое предприятие по интеграции C и Python 2.7.3. Для начала я просто пытаюсь написать модуль C для Python, который может делать базовое дополнение. (Это называется npfind, потому что, как только я понять это, я хочу написать метод поиска для NumPy)Интеграция C и Python: ValueError: функции модуля не могут установить METH_CLASS или METH_STATIC

npfind.h:

#include <math.h> 

extern int add(int a, int b); 

npfind.c:

#include "npfind.h" 

int add(int a, int b) 
{ 
    return a + b; 
} 

pynpfind. с:

#include "Python.h" 
#include "npfind.h" 

static char* py_add_doc = "Adds two numbers."; 
static PyObject* py_add(PyObject* self, PyObject* args) 
{ 
    int a, b, r; 

    if (!PyArg_ParseTuple(args, "ii", &a, &b)) 
    { 
     return NULL; 
    } 

    r = a + b; 

    return Py_BuildValue("i", r); 
} 

static PyMethodDef* _npfindmethods = { 
    {"add", py_add, METH_VARARGS, py_add_doc}, 
    {NULL, NULL, 0, NULL} 
}; 

void init_npfind(void) 
{ 
    PyObject* mod; 
    mod = Py_InitModule("_npfind", _npfindmethods); 
} 

npfind.py:

from _npfind import * 

#Do stuff with the methods 

npfindsetup.py

from distutils.core import setup, Extension 

setup(name="npfind", version="1.0", py_modules = ['npfind.py'], 
     ext_modules=[Extension("_npfind", ["pynpfind.c", "npfind.c"])]) 

После всего этого, на Windows 7, я типа

python npfindsetup.py build_ext --inplace --compiler=mingw32 

который, кажется, работает. Когда я затем попытаться найти npfind.py, я получаю эту ошибку:

Traceback (most recent call last): 
    File "npfind.py", line 1, in <module> 
    from _npfind import * 
ValueError: module functions cannot set METH_CLASS or METH_STATIC 

Я не могу понять, что это говорит. Что такое METH_CLASS и METH_STATIC, и почему я пытаюсь их установить?

ответ

3

Вы объявляете _npfindmethods в качестве указателя и пытаетесь инициализировать его как массив. Когда я построить код, скопированный из ваших фрагментов, я получаю много предупреждений, как:

a.c:24:5: warning: braces around scalar initializer [enabled by default] 
a.c:24:5: warning: (near initialization for '_npfindmethods') [enabled by default] 
a.c:24:5: warning: initialization from incompatible pointer type [enabled by default] 
a.c:24:5: warning: (near initialization for '_npfindmethods') [enabled by default] 
(...) 

переменные инициализируются с неверным значением, и, таким образом, Python находит случайные данные внутри.


Вы должны объявить _npfindmethods как массив вместо:

static PyMethodDef _npfindmethods[] = { 
    {"add", py_add, METH_VARARGS, py_add_doc}, 
    {NULL, NULL, 0, NULL} 
}; 

Теперь он будет инициализирован, как вы ожидаете. Кроме того, поскольку в настоящее время py_add_doc должен иметь постоянный адрес, вы должны сделать это массив, а также:

static char py_add_doc[] = "Adds two numbers."; 

Итак, ваш окончательный pynpfind.c будет выглядеть так:

#include "Python.h" 
#include "npfind.h" 

static char py_add_doc[] = "Adds two numbers."; 
static PyObject* py_add(PyObject* self, PyObject* args) 
{ 
    int a, b, r; 

    if (!PyArg_ParseTuple(args, "ii", &a, &b)) 
    { 
     return NULL; 
    } 

    r = a + b; 

    return Py_BuildValue("i", r); 
} 

static PyMethodDef _npfindmethods[] = { 
    {"add", py_add, METH_VARARGS, py_add_doc}, 
    {NULL, NULL, 0, NULL} 
}; 

void init_npfind(void) 
{ 
    PyObject* mod; 
    mod = Py_InitModule("_npfind", _npfindmethods); 
} 
+0

Спасибо. Я не знал о существовании каких-либо функциональных различий между указателями и массивами в C. – dpitch40

+0

В основном это касается хранения. Локальный массив означает, что C выделяет пространство для хранения всего массива. Указатель означает, что для массива есть только место для адреса памяти, и тогда вам нужно будет выделить массив где-то еще. –

+0

Не указатель на массив должен быть char **? – dpitch40

 Смежные вопросы

  • Нет связанных вопросов^_^