【问题标题】:Extending Python with C Error: Segmentation Fault: 11 in Python [MacOS X]使用 C 错误扩展 Python:分段错误:Python 中的 11 [MacOS X]
【发布时间】:2018-11-26 18:10:31
【问题描述】:

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

构建“ext”扩展 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/anacon nda3/include/python3.6m -c extmodule.c -o 构建/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) ^~~~~~ /Users/somdipdey/anaconda3/include/python3.6m/modsupport.h:150:60: 注意:在此处将参数传递给参数 PyAPI_FUNC(PyObject ) PyModule_Create2(struct 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/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 程序中 import ext 并使用函数 ext.cpu(integer_value) 时,程序给了我以下错误:

分段错误:11

知道可能导致问题的原因以及如何解决它吗?

【问题讨论】:

  • ncompatible pointer types passing 'PyMethodDef (*)[1]' to &gt; parameter of type &gt; 'struct PyModuleDef *' 这是一个严重的警告。意味着底层代码将读取一个 pymodule 但你传递了一个 pymethod...
  • @Jean-FrançoisFabre 我正在按照教程编写代码,所以我不知道如何实现这一点。请问你碰巧知道我该如何解决它吗?教程:youtube.com/watch?v=s6cvSkbWG3s
  • 你需要阅读the actual docs。此外,虽然为了看看所有部分是什么而努力一次是值得的,除非你真的喜欢低级 C 编程,否则你应该认真考虑用 Cython 编写扩展,或者至少用稍微高级一点的语言可以为您自动化所有烦人的东西的库,例如带有 PyCxx、Boost 或 CPyExt 的 C++、带有 Pyd 的 D、带有 rust-python 的 Rust 等。不再需要处理难以调试的表、引用计数等问题。
  • 另外,在某些情况下,使用普通旧 C API 编写 C 库会更容易,构建为普通旧 dylib/so/dll,然后使用 cffictypes 来从 Python 或 SWIG 之类的库中包装它以自动构建包装器。
  • @abarnert 我对这些东西完全陌生。曾是 C# 程序员,但现在来到 C 领域。最重要的是进行低级 C 编程的原因是访问硬件的每个性能计数器,因此构建 c 扩展程序以便能够从 python 程序中使用它(我肯定使用 python 比使用 C 更舒服)。无论如何,您认为我可以使用 Cython 进行如此低级的 C 编程吗?

标签: python distutils


【解决方案1】:

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

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


如果你解决了这个问题,你可能有也可能没有另一个段错误、垃圾数据或退出时出现的神秘段错误,因为你的方法表最后缺少空行。 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

……一切正常。

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

【讨论】:

    猜你喜欢
    • 2019-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多