Расширение Python с помощью ошибки C: Ошибка сегментации: 11 в Python [MacOS X]

1

Я написал модуль расширения в C с именем extmodule.c, и код для него следующий:

#include <Python.h>

//Define a new exception object for our module
static PyObject *extError;

static PyObject* ext_cpu(PyObject* self, PyObject *args)
{
  int pid;
  int sts=0;

  //We expect at least 1 argument to this function
  if(!PyArg_ParseTuple(args, "i", &pid))
  {
    return NULL;
  }


  printf("Hello, from C World! Pid: %i", pid);
  sts=pid;

  return Py_BuildValue("i", sts);
}

static PyMethodDef ext_methods[] = {
  //PythonName, C-FunctionName, argument_presentation, description
  {"cpu", ext_cpu, METH_VARARGS, "Print cpu consumption of a particular process with pid"}
};

PyMODINIT_FUNC
PyInit_ext(void)
{
    PyObject *m;

    m = PyModule_Create(&ext_methods);
    if (m == NULL)
        return NULL;

    extError = PyErr_NewException("spam.error", NULL, NULL);
    Py_INCREF(extError);
    PyModule_AddObject(m, "error", extError);
    return m;
}

После этого я создал setup.py для создания и установки файла расширения в моей программе python, а код для setup.py выглядит следующим образом:

from distutils.core import setup, Extension

module1 = Extension('ext',
    include_dirs = ['/usr/local/include'],
    libraries = ['pthread'],
    sources = ['extmodule.c'])

setup (name = 'ext',
    version = '1.0',
    description = 'This is a C extension for Python program',
    author = 'Somdip Dey',
    url = '',
    ext_modules = [module1])

Теперь в командной строке я создал setup.py, используя следующие команды:

>> python setup.py build

run build running build_ext

расширение 'ext' gcc -Wno-unused-result -Wsign -c ompare -Wunreachable -c ode -DNDEBUG -g -fwrapv -o 3 -Wall -Wstrict-прототипы -I/Пользователи /somdipdey/anaconda3/include -arch x86_64 -I/Пользователи /somdipdey/anaconda3/include -arch x86_64 -I/usr/local/include -I/Пользователи /somdipdey/anaco nda3/include/python3.6m [CN09 ] extmodule.c -o build/temp. macosx- 10.7-x86_64-3.6/extmodule.o extmodule.c: 34: 25: предупреждение: несовместимые типы указателей, передающие 'PyMethodDef (*) [1]' параметру типа 'struct PyModuleDef *' [-Wincompatible-pointer-types] m = PyModule_Create (& ext_methods); /Users/somdipdey/anaconda3/include/python3.6m/modsupport.h:158:26: примечание: расширено от макроса 'PyModule_Create' PyModule_Create2 (модуль, PYTHON_API_VERSION) ^ ~~~~~/Пользователи /somdipdey/anaconda3/include/python3.6m/modsupport.h: 150: 60: note: передайте аргумент параметру здесь PyAPI_FUNC (PyObject) PyModule_Create2 (генерируется предупреждение о генерации PyModuleDef, ^ 1. gcc -bundle -undefined dynamic_lookup -L/Пользователи /somdipdey/anaconda3/lib -arch x86_64 -L/Пользователи /somdipdey/anaconda3/lib -arch x86 _64 -arch x86_64 build/temp. macosx- 10.7-x86_64-3.6/extmodule.o -L/Пользователи /somdipdey/anaconda3/lib -L pthread -o build/lib. macosx- 10.7-x86_64-3.6/ext.cpython-36m-darwin.so

>> python setup.py install

Команда установки работала правильно, но сборка дала 1 предупреждение. Теперь, когда я пытаюсь импортировать ext в мою программу python и использовать функцию ext.cpu(integer_value), программа дает мне следующую ошибку:

Ошибка сегментации: 11

Любая идея, что может вызвать проблему и как ее избавиться?

Теги:
distutils

1 ответ

2
Лучший ответ

Предупреждение сообщает вам, что именно неправильно: вы передаете PyMethodDef (*)[1] в PyModule_Create, когда он ожидает PyModuleDef *. Это совершенно несвязанные типы. Полученный вами segfault похож на C-версию TypeError.

Вам нужно создать таблицу определения модуля и передать ее PyModule_Create.


Если вы исправите это, вы можете или не иметь другого segfault, или данные мусора, или загадочный segfault при выходе, потому что в таблице методов отсутствует пустая строка в конце. C не знают своего размера, как это делают списки Python, поэтому код, который их использует, либо должен проходить вокруг размера в отдельной переменной, либо использовать какое-то "контрольное" значение в последнем слоте. PyMethodDef использует последнее решение.


Так:

static PyMethodDef ext_methods[] = {
  //PythonName, C-FunctionName, argument_presentation, description
  {"cpu", ext_cpu, METH_VARARGS, "Print cpu consumption of a particular process with pid"},
  {NULL, NULL, 0, NULL}
};

static struct PyModuleDef ext_module = {
  PyModuleDef_HEAD_INIT,
  "ext",
  "Extension module that does stuff",
  -1,
  ext_methods
};

PyMODINIT_FUNC
PyInit_ext(void)
{
    PyObject *m;

    m = PyModule_Create(&ext_module);
    // the rest is the same as before

С этими изменениями ваш модуль строит без предупреждений и:

>>> import ext
>>> ext.cpu(23)
Hello, from C World! Pid: 23
>>> ^D

... все работает нормально.

(Ну, там может быть утечка памяти, но это отдельная проблема...)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню