Python C Extension会引发Segmentation Fault

时间:2018-06-12 18:07:57

标签: python c

#include <Python.h>
#include <math.h>

static PyObject* interpolate(PyObject* self, PyObject* args) {
    const Py_ssize_t tl = 2;
    const Py_ssize_t ll = 0;
    int nx, ny, angle, distance;
    if (!PyArg_ParseTuple(args, "iiii", &nx, &ny, &angle, &distance)) {
        return NULL;
    }
    PyObject* pos_list = PyList_New(ll);
    for (int i = 0; i < distance; i++) {
        double x = -i * cos(angle * M_PI / 180);
        double y = -i * sin(angle * M_PI / 180);
        PyObject *pos = PyTuple_Pack(tl, x, y);
        PyList_Append(pos_list, pos);
    }
    return pos_list;
}

从Python导入模块时,代码不断抛出分段错误。不太清楚为什么会发生这种情况,因为我对C和C扩展程序来说真的很陌生。我不确定我是否正确地执行了setup.py代码。我认为错误与我返回pos_list变量和math.h没有正确包含有关。当我删除math.h sin和cos的东西并切换到Py_BuildValue一个简单的整数时,它就可以工作。

from distutils.core import setup, Extension

module1 = Extension('gameMath',
                    sources = ['interpolate.c'],
                    include_dirs = ['/usr/include'],
                    libraries = ['math'])
setup (name = 'gameMath',
        version = '1.0',
        description = 'game math',
        ext_modules = [module1])

1 个答案:

答案 0 :(得分:1)

这里可能存在多个问题,但是,假设模块样板文件是正确的(你还没有包含它),并且你的setup.py对于实际构建代码是正确的(它不是发布的),而你我以明显的方式称呼这个,这里至少有一个可能的段错误:

float

作为PyTuple_Pack文件:

  

返回一个大小为 n 的新元组对象,或者在失败时返回 NULL 。元组值初始化为后续 n C参数指向Python对象

你没有将指针传递给Python对象,你传递的是双倍的。因此,它会尝试将每个double解释为指针,这很可能是段错误。 1

您需要使用PyFloat_FromDoublePy_BuildValue构建两个Python PyObject *pos = Py_BuildValue("(ff)", x, y); 对象,以便即时转换它们:

-2.0

A completed and cleaned-up version with this fix似乎有效。

<子> 1。如果你不知道足够的C,但想知道它崩溃的原因:假设这里有64位,你要求它将double的64位解释为指针。比方说,0xC000000000000000,这是指向PyObject的指针。哪个可能不在分配的内存中,更不用说指向有效import static org.hamcrest.CoreMatchers.is; 结构的指针,其指针本身指向已分配的内存,即使分配了所有这些页面,它们中的一个页面也可能是只读的因此,例如,引用计数增量失败。