#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/