2015-02-03 2 views
7

Я пытаюсь написать расширение C для python. С кодом (ниже) я получаю предупреждение компилятора:Компилятор не может найти Py_InitModule() .. он устарел, и если да, то что я должен использовать?

implicit declaration of function ‘Py_InitModule’ 

И он терпит неудачу во время выполнения с этой ошибкой:

undefined symbol: Py_InitModule 

Я потратил буквально часы на поиски решения, без радости. Я пробовал несколько незначительных изменений в синтаксисе, я даже нашел сообщение о том, что метод устарел. Однако я не нахожу замены.

Вот код:

#include <Python.h> 

//a func to calc fib numbers 
int cFib(int n) 
{ 
    if (n<2) return n; 
    return cFib(n-1) + cFib(n-2); 
} 


static PyObject* fib(PyObject* self,PyObject* args) 
{ 
    int n; 
    if (!PyArg_ParseTuple(args,"i",&n)) 
     return NULL;  
    return Py_BuildValue("i",cFib(n)); 
} 

static PyMethodDef module_methods[] = { 
    {"fib",(PyCFunction) fib, METH_VARARGS,"calculates the fibonachi number"}, 
    {NULL,NULL,0,NULL} 
}; 

PyMODINIT_FUNC initcModPyDem(void) 
{ 
    Py_InitModule("cModPyDem",module_methods,"a module"); 
} 

Если это помогает здесь мой setup.py:

from distutils.core import setup, Extension 

module = Extension('cModPyDem', sources=['cModPyDem.c']) 
setup(name = 'packagename', 
    version='1.0', 
    description = 'a test package', 
    ext_modules = [module]) 

И тест-код в test.py:

import cModPyDem 

if __name__ == '__main__' : 

    print(cModPyDem.fib(200)) 

Любой помощь будет очень, высоко оценена.

+0

какая версия Python вы компилируете? – MattDMo

+0

Извините, я компилирую с python3 –

ответ

20

Код, который у вас будет работать в Python 2.x, но Py_InitModule больше не используется в Python 3.x. В настоящее время вы создаете структуру PyModuleDef, а затем передаете ссылку на нее PyModule_Create.

структура будет выглядеть следующим образом:

static struct PyModuleDef cModPyDem = 
{ 
    PyModuleDef_HEAD_INIT, 
    "cModPyDem", /* name of module */ 
    "",   /* module documentation, may be NULL */ 
    -1,   /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ 
    module_methods 
}; 

И тогда ваша PyMODINIT_FUNC функция будет выглядеть следующим образом:

PyMODINIT_FUNC PyInit_cModPyDem(void) 
{ 
    return PyModule_Create(&cModPyDem); 
} 

Обратите внимание, что имя функции PyMODINIT_FUNC должен иметь вид PyInit_<name> где <name> является имя вашего модуля.

Я думаю, что было бы полезно, если бы вы прочитали Extending в документации Python 3.x. Он содержит подробное описание того, как создавать модули расширения в современном Python.

+0

Отлично - код, который вы предоставили, работает как есть, кроме одного незначительного изменения - PyMODINIT_FUNC PyInit_cModPyDem (void) {} ​​- правильный путь. Спасибо, и да, стоило пройти через документы. –

+0

В 'return PyModule_Create (& ModPyDem);', правильным будет 'return PyModule_Create (& cModPyDem);'? – Macabeus

+0

@Macabeus - Да, спасибо, что поймали это. – iCodez

0

Я столкнулся с той же проблемой с Py_InitModule(). Я начал работу с вышеупомянутыми документами Python 3, в частности, с документом «Расширение и внедрение документа Python Interpreter». Но глава этого документа, озаглавленная «Простой пример», не содержит подробностей. Так. Я гугл этого SciPy лекции:

http://www.scipy-lectures.org/advanced/interfacing_with_c/interfacing_with_c.html

, которая во многих отношениях более подходит для кого-то нового для расширений API Python-C ... за исключением того, что не было обновлено для Python v3. Итак ... проконсультируйтесь с лекцией scipy и с документами Python 3 и с этим обсуждением в StackOverflow, отбраковав соответствующую информацию от каждого для ваших нужд.