2016-06-07 2 views
-1

От чтения другого post, я пытаюсь embbed некоторого кода Python в C:Вложение Python в C - Segfault

main.c

#include <Python.h> 

int callModuleFunc(int array[], size_t size) { 
    PyObject *mymodule = PyImport_ImportModule("py_function"); 
    PyObject *myfunc = PyObject_GetAttrString(mymodule, "printlist"); 
    PyObject *mylist = PyList_New(size); 
    for (size_t i = 0; i != size; ++i) { 
     PyList_SET_ITEM(mylist, i, PyInt_FromLong(array[i])); 
    } 
    PyObject *arglist = Py_BuildValue("(o)", mylist); 
    PyObject *result = PyObject_CallObject(myfunc, arglist); 
    int retval = (int)PyInt_AsLong(result); 
    Py_DECREF(result); 
    Py_DECREF(arglist); 
    Py_DECREF(mylist); 
    Py_DECREF(myfunc); 
    Py_DECREF(mymodule); 
    return retval; 
} 

int main(int argc, char *argv[]) 
{ 
    int a[] = {1,2,3,4}; 
    callModuleFunc(a, 4); 
    return 0; 
} 

py_function.py

'''py_function.py - Python source designed to ''' 
'''demonstrate the use of python embedding''' 

def printlist(mylist): 
    print mylist 

Затем я составил:

gcc main.c -I/usr/include/python2.7 -lpython2.7 

Но тогда я побежал приложение, он дает мне ошибку ошибки сегментации:

/a.out 
[1] 18890 segmentation fault ./a.out 

Есть ли что-то, что мне не хватает?

+0

Вы назначаете целую кучу указателей из возвращаемых значений функции вызовы, но не проверяйте их достоверность перед их использованием. Вы также можете смешивать типы - вы получаете предупреждения о компиляции? (Хотя в C даже отсутствие такого не подразумевает, что таких проблем нет). Вы также можете рассмотреть возможность запуска вашей программы под отладчиком, а затем с помощью команды backtrace или того, что ваш отладчик вызывает для проверки стека, и посмотрите, где произошел сбой произошло. –

ответ

3

Были некоторые проблемы с вашим кодом:

  1. Py_Initialize() не называлась.
  2. PyImport_ImportModule() не удалось найти ваш файл python, так как во встроенном Python вы начинаете без исходного модуля, относительно которого поиск может работать. Исправление состоит в том, чтобы явно включить текущий каталог в sys.path.
  3. "(O)" в Py_BuildValue() следует использовать капитал 'O'.
  4. Функция printlist должна возвращать значение (так как это ожидаемый C-код).

Это должно работать:

main.c

#include <Python.h> 

void initPython() 
{ 
    Py_Initialize(); 
    PyObject *sysmodule = PyImport_ImportModule("sys"); 
    PyObject *syspath = PyObject_GetAttrString(sysmodule, "path"); 
    PyList_Append(syspath, PyString_FromString(".")); 
    Py_DECREF(syspath); 
    Py_DECREF(sysmodule); 
} 

int callModuleFunc(int array[], size_t size) { 
    PyObject *mymodule = PyImport_ImportModule("py_function"); 
    assert(mymodule != NULL); 
    PyObject *myfunc = PyObject_GetAttrString(mymodule, "printlist"); 
    assert(myfunc != NULL); 
    PyObject *mylist = PyList_New(size); 
    for (size_t i = 0; i != size; ++i) { 
     PyList_SET_ITEM(mylist, i, PyInt_FromLong(array[i])); 
    } 
    PyObject *arglist = Py_BuildValue("(O)", mylist); 
    assert(arglist != NULL); 
    PyObject *result = PyObject_CallObject(myfunc, arglist); 
    assert(result != NULL); 
    int retval = (int)PyInt_AsLong(result); 
    Py_DECREF(result); 
    Py_DECREF(arglist); 
    Py_DECREF(mylist); 
    Py_DECREF(myfunc); 
    Py_DECREF(mymodule); 
    return retval; 
} 

int main(int argc, char *argv[]) 
{ 
    initPython(); 

    int a[] = {1,2,3,4,5,6,7}; 
    callModuleFunc(a, 4); 
    callModuleFunc(a+2, 5); 

    Py_Finalize(); 
    return 0; 
} 

py_function.py

'''py_function.py - Python source designed to ''' 
'''demonstrate the use of python embedding''' 

def printlist(mylist): 
    print mylist 
    return 0 
+0

Привет, Леон, он работает. Теперь я попытался добавить numpy в источник python, но он дает мне: 'main.c: 18: callModuleFunc: Assertion' mymodule! = ((Void *) 0) «failed». Знаете ли вы, что я должен делать с моим C-кодом, когда я импортирую другие библиотеки в Python? – FacundoGFlores

+1

Вы «импортировали numpy' в' py_function.py'? Работает ли он без проблем при запуске 'py_function.py' с помощью python напрямую? Если это так, то проблема, вероятно, будет устранена путем правильного заполнения 'sys.path'. – Leon

+0

Модуль python корректно работает вне моей программы на C. Что вы подразумеваете под «правильно заполняющим sys.path»? Я вижу следующий пример: https://github.com/Frogee/PythonCAPI_testing/blob/master/testEmbed.cpp, и он, похоже, не помещает ничего, кроме модуля «sys», как вы положили его в приведенном выше примере. – FacundoGFlores

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