用C语言扩展Python错误:分段错误:Python中的11 [MacOS X]

时间:2018-06-17 20:36:32

标签: python distutils

我在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
  

运行构建   运行build_ext

     

建筑&#39;分机&#39;扩展gcc   -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I / Users / somdipdey / anaconda3 / include -arch x86_64 -I / Users / somdipdey / anaconda3 /包括   -arch x86_64 -I / usr / local / include -I / Users / somdipdey / anaco nda3 / include / python3.6m -c extmodule.c -o   build / temp.macosx-10.7-x86_64-3.6 / extmodule.o extmodule.c:34:25:   警告:不兼容的指针类型传递&#39; PyMethodDef(*)[1]&#39;至   类型的参数         &#39; struct PyModuleDef *&#39; [-Wincompatible指针类型]       m = PyModule_Create(&amp; ext_methods);   /Users/somdipdey/anaconda3/include/python3.6m/modsupport.h:158:26:   注意:从宏观扩展到PyModule_Create&#39;           PyModule_Create2(模块,PYTHON_API_VERSION)                            ^ ~~~~~ /Users/somdipdey/anaconda3/include/python3.6m/modsupport.h:150:60:   注意:将参数传递给参数PyAPI_FUNC(PyObject )   PyModule_Create2(struct PyModuleDef ,                                                              生成^ 1警告。 gcc -bundle -undefined dynamic_lookup   -L / Users / somdipdey / anaconda3 / lib -arch x86_64 -L / Users / somdipdey / anaconda3 / lib -arch x86   _64 -arch x86_64 build / temp.macosx-10.7-x86_64-3.6 / extmodule.o -L / Users / somdipdey / anaconda3 / lib -lpthread -o build / lib.macosx-   10.7-x86_64-3.6 / ext.cpython-36m-darwin.so

>> python setup.py install

安装命令工作正常,但构建版本1发出警告。现在,当我在我的python程序中尝试导入ext 并使用函数 ext.cpu(integer_value)时,该程序给出了以下错误:

  

分段错误:11

知道可能导致问题的原因以及如何摆脱它?

1 个答案:

答案 0 :(得分:2)

警告告诉您到底出了什么问题:当您预期PyMethodDef (*)[1]时,您将PyModule_Create传递给PyModuleDef *。那些是完全不相关的类型。您获得的段错误就像TypeError的C版本。

You need to create a module definition table,并将 传递给PyModule_Create

如果你修复了这个问题,你可能会或者可能没有其他段错误,垃圾数据或退出时出现神秘的段错误,因为你的方法表在结尾处缺少空行。 C数组不像Python列表那样知道它们的大小,因此使用它们的代码需要在单独的变量中传递大小,或者在最后一个槽中使用一些“sentinel”值。 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

......一切正常。

(好吧,那里可能存在内存泄漏,但这是一个单独的问题......)