Python C 扩展抛出段错误

标签 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])

最佳答案

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

PyObject *pos = PyTuple_Pack(tl, x, y);

作为PyTuple_Pack文件:

Return a new tuple object of size n, or NULL on failure. The tuple values are initialized to the subsequent n C arguments pointing to Python objects.

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

您要么需要使用 PyFloat_FromDouble 构造两个 Python float 对象, 或 Py_BuildValue即时转换它们:

PyObject *pos = Py_BuildValue("(ff)", x, y);

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


<子>1。如果您对 C 了解不够,但想知道它崩溃的原因:假设这里是 64 位,您要求它将 double 的 64 位解释为指针。例如,-2.0,这是指向 0xC000000000000000 的指针。这很可能不在分配的内存中,更不用说指向有效 PyObject 结构的指针,该结构的指针本身指向分配的内存,即使分配了所有此类页面,也可能其中一个页面将是只读的,例如,引用计数增量失败。

关于Python C 扩展抛出段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50823256/

相关文章:

python - 在我的批处理文件重命名和移动脚本中遇到 Python os.rename() 问题

python - 解释 sklearn TfidfVectorizer 中的 TF-IDF 分数

python - excel 文件处理 xlrd 期间的 pytest 警告

c - 运行需要服务管理员帐户的应用程序

适用于 Microsoft Windows CE 7.0 的 Visual Studio 2015 中的 Python

python - 我如何组合 wxPython、abc 和元类 mixin?

c - 在嵌入式系统中使用setcontext()、getcontext()

c - 循环解析器

C - 在跟踪索引的同时对 float 组进行排序

在没有 malloc 的情况下创建内存缓冲区