Python 尝试写入C扩展中创建的Numpy数组时出现SEGFULT

Python 尝试写入C扩展中创建的Numpy数组时出现SEGFULT,python,c,python-c-api,Python,C,Python C Api,我在for循环中有一个if子句,在该子句中我预先定义了state_out: state_out = (PyArrayObject *) PyArray_FromDims(1,dims_new,NPY_BOOL); 如果条件是这样的: if (conn_ctr<sum*2){ *(state_out->data + i*state_out->strides[0]) = true; } else {

我在for循环中有一个if子句,在该子句中我预先定义了state_out:

state_out = (PyArrayObject *) PyArray_FromDims(1,dims_new,NPY_BOOL);
如果条件是这样的:

        if (conn_ctr<sum*2){
            *(state_out->data + i*state_out->strides[0]) =  true;
        }
        else {
            *(state_out->data + i*state_out->strides[0]) =  false;
        }
我又犯错误了

非常感谢,下面是代码的其余部分

#include <Python.h>
#include "numpy/arrayobject.h"
#include <stdio.h>
#include <stdbool.h>

static PyObject* trace(PyObject *self, PyObject *args);

static char doc[] =
"This is the C extension for xor_masking routine. It interfaces with Python via C-Api, and calculates the"
"next state with C pointer arithmetic";

static PyMethodDef TraceMethods[] = {
    {"trace", trace, METH_VARARGS, doc},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
inittrace(void)
{
    (void) Py_InitModule("trace", TraceMethods);
    import_array();
}

static PyObject* trace(PyObject *self, PyObject *args){
    PyObject *adjacency ,*mask, *state;
    PyArrayObject *adjacency_arr, *mask_arr, *state_arr, *state_out;

    if (!PyArg_ParseTuple(args,"OOO:trace", &adjacency, &mask, &state)) return NULL;

    adjacency_arr = (PyArrayObject *)
        PyArray_ContiguousFromObject(adjacency, NPY_BOOL,2,2);

    if (adjacency_arr == NULL) return NULL;
    mask_arr = (PyArrayObject *)
        PyArray_ContiguousFromObject(mask, NPY_BOOL,2,2);

    if (mask_arr == NULL) return NULL;
    state_arr = (PyArrayObject *)
        PyArray_ContiguousFromObject(state, NPY_BOOL,1,1);

    if (state_arr == NULL) return NULL;

    int dims[2], dims_new[1];
    dims[0] = adjacency_arr -> dimensions[0];
    dims[1] = adjacency_arr -> dimensions[1];
    dims_new[0] =  adjacency_arr -> dimensions[0];
    if (!(dims[0]==dims[1] && mask_arr -> dimensions[0] == dims[0]
                         && mask_arr -> dimensions[1] == dims[0]
                         && state_arr -> dimensions[0] == dims[0]))
                         return NULL;


    state_out = (PyArrayObject *) PyArray_FromDims(1,dims_new,NPY_BOOL);

    int i,j;

    for(i=0;i<dims[0];i++){
        int sum = 0;
        int conn_ctr = 0;

            for(j=0;j<dims[1];j++){

                bool adj_value = (adjacency_arr->data + i*adjacency_arr->strides[0]
                         +j*adjacency_arr->strides[1]);

                if (*(bool *) adj_value == true){

                    bool mask_value = (mask_arr->data + i*mask_arr->strides[0]
                    +j*mask_arr->strides[1]);
                    bool state_value = (state_arr->data + j*state_arr->strides[0]);

                    if ( (*(bool *) mask_value ^ *(bool *)state_value) ==  true){
                        sum++;
                    }
                    conn_ctr++;
                }
            }

            if (conn_ctr<sum*2){

            }
            else {

            }
    }

    Py_DECREF(adjacency_arr);
    Py_DECREF(mask_arr);
    Py_DECREF(state_arr);
    return PyArray_Return(state_out);
}
#包括
#包括“numpy/arrayobject.h”
#包括
#包括
静态PyObject*跟踪(PyObject*self,PyObject*args);
静态字符doc[]=
这是xor_掩蔽例程的C扩展。它通过C-Api与Python接口,并计算
“使用C指针算法的下一个状态”;
静态PyMethodDef TraceMethods[]={
{“trace”,trace,METH_VARARGS,doc},
{NULL,NULL,0,NULL}
};
PyMODINIT_FUNC
初始跟踪(无效)
{
(void)Py_InitModule(“trace”,TraceMethods);
导入数组();
}
静态PyObject*跟踪(PyObject*self,PyObject*args){
PyObject*邻接,*掩码,*状态;
PyArrayObject*邻接,*屏蔽,*状态,*状态输出;
if(!PyArg_ParseTuple(args,“OOO:trace”、&邻接、掩码和状态))返回NULL;
邻接_arr=(PyArrayObject*)
PyArray_ContiguousFromObject(邻接,NPY_BOOL,2,2);
if(adjacency_arr==NULL)返回NULL;
掩码_arr=(PyArrayObject*)
PyArray_ContinguousFromObject(掩码,NPY_布尔,2,2);
if(mask_arr==NULL)返回NULL;
状态_arr=(PyArrayObject*)
PyArray_ContiguousFromObject(state,NPY_BOOL,1,1);
if(state_arr==NULL)返回NULL;
int dims[2],dims_new[1];
dims[0]=相邻区域->尺寸[0];
dims[1]=相邻区域->尺寸[1];
dims_new[0]=邻接arr->尺寸[0];
如果(!(dims[0]==dims[1]&&mask_arr->尺寸[0]==dims[0]
&&遮罩阵列->尺寸[1]==dims[0]
&&状态->尺寸[0]==dims[0]))
返回NULL;
state_out=(PyArrayObject*)PyArray_FromDims(1,dims_new,NPY_BOOL);
int i,j;
对于(i=0;istrides[0]
+j*相邻距离->跨步[1];
如果(*(bool*)调整值==真){
bool mask\u value=(mask\u arr->data+i*mask\u arr->步幅[0]
+j*遮罩->跨步[1];
bool state_value=(state_arr->data+j*state_arr->strips[0]);
if((*(bool*)掩码_值^*(bool*)状态_值)==true){
sum++;
}
conn_ctr++;
}
}
如果(连接中心
这是我复制到这里的一部分。state\u out->strips是一个指向数组长度的指针,数组的维数是我们拥有的。在这种情况下,这是一个1d数组。所以当我做指针算术
(state\u out->data+I*state\u out->strips[0])
我的目标当然是计算指向数组第I个值的指针,但我没有给出指针的类型,因此

我试过:

NPY_BOOL *adj_value_ptr, *mask_value_ptr, *state_value_ptr, *state_out_ptr;
其中变量指向我对for循环感兴趣的值,state_out_ptr就是我要写的 这些数组的组成部分属于
NPY\u BOOL
类型,指向数组中数据的指针也属于
NPY\u BOOL
类型。当直接操作内存处理数据时,这会因SegFault而失败。这是因为NPY\u BOOL是整数的
enum
(如评论中所述。)对于NumPy内部使用,.有一个C
typedef
npy\u bool
,以便在代码中使用布尔值。
。当我介绍我的指针时

npy_bool *adj_value_ptr, *mask_value_ptr, *state_value_ptr, *state_out_ptr;
分割错误消失了,我成功地操作并返回了一个Numpy数组

我不是专家,但这解决了我的问题,指出我的错误

源代码中已更改的部分是:

state_out = (PyArrayObject *) PyArray_FromDims(1,dims_new,NPY_BOOL);

npy_bool *adj_value_ptr, *mask_value_ptr, *state_value_ptr, *state_out_ptr;
npy_intp i,j;

for(i=0;i<dims[0];i++){
    npy_int sum = 0;
    npy_int conn_ctr = 0;

        for(j=0;j<dims[1];j++){

            adj_value_ptr = (adjacency_arr->data + i*adjacency_arr->strides[0]
                     +j*adjacency_arr->strides[1]);

            if (*adj_value_ptr == true){

                mask_value_ptr = (mask_arr->data + i*mask_arr->strides[0]
                +j*mask_arr->strides[1]);

                state_value_ptr = (state_arr->data + j*state_arr->strides[0]);

                if ( (*(bool *) mask_value_ptr ^ *(bool *)state_value_ptr) ==  true){
                    sum++;
                }
                conn_ctr++;
            }
        }
        state_out_ptr = (state_out->data + i*state_out->strides[0]);
        if (conn_ctr < sum*2){
            *state_out_ptr =  true;
        }
        else {
            *state_out_ptr =  false;
        }
}
state_out=(PyArrayObject*)PyArray_FromDims(1,dims_new,NPY_BOOL);
npy布尔*调整值ptr、*掩码值ptr、*状态值ptr、*状态输出ptr;
npy_intp i,j;
对于(i=0;istrides[0]
+j*相邻距离->跨步[1];
如果(*adj_值_ptr==真){
掩码值\u ptr=(掩码\u arr->data+i*掩码\u arr->步幅[0]
+j*遮罩->跨步[1];
state_value_ptr=(state_arr->data+j*state_arr->strips[0]);
如果((*(bool*)掩码_值_ptr^*(bool*)状态_值_ptr)==true){
sum++;
}
conn_ctr++;
}
}
state_out_ptr=(state_out->data+i*state_out->strips[0]);
如果(连接中心<总和*2){
*state_out_ptr=true;
}
否则{
*state_out_ptr=false;
}
}

您正在使用
bool
变量来存储指针/地址。
NPY\u bool
unsigned char
)和
bool
在您的平台上可能不一样。我尝试键入true of false:
(unsigned char)是的
也不一样。我还尝试分配1或0,我猜这是我之前的做法。
*(state\u out->data+I*state\u out->strips[0])=1;
也会因SegFault而失败。请发布完整的Python测试代码,包括输入数据和预期输出。@cgohlke的上述注释意味着您在处理指向布尔值的指针时应该编写例如
npy_bool*adj_value=…
而不是
bool adj_value=…
。但代码可能在某些pl上失败因为1)铸造
npy\u bool*
bool*
和2)使用
int
而不是
npy\u intp
进行尺寸/反作用力是的,我应该在所有条件下使用npy\u bool*。这真的很有帮助,我会试试看。但是I XOR不是为npy_bools定义的,所以我必须至少对其他的进行类型转换,以避免4个if子句的序列。我更改了答案中的所有其他内容。
npy\u bool
是C
NPY_BOOL *adj_value_ptr, *mask_value_ptr, *state_value_ptr, *state_out_ptr;
npy_bool *adj_value_ptr, *mask_value_ptr, *state_value_ptr, *state_out_ptr;
state_out = (PyArrayObject *) PyArray_FromDims(1,dims_new,NPY_BOOL);

npy_bool *adj_value_ptr, *mask_value_ptr, *state_value_ptr, *state_out_ptr;
npy_intp i,j;

for(i=0;i<dims[0];i++){
    npy_int sum = 0;
    npy_int conn_ctr = 0;

        for(j=0;j<dims[1];j++){

            adj_value_ptr = (adjacency_arr->data + i*adjacency_arr->strides[0]
                     +j*adjacency_arr->strides[1]);

            if (*adj_value_ptr == true){

                mask_value_ptr = (mask_arr->data + i*mask_arr->strides[0]
                +j*mask_arr->strides[1]);

                state_value_ptr = (state_arr->data + j*state_arr->strides[0]);

                if ( (*(bool *) mask_value_ptr ^ *(bool *)state_value_ptr) ==  true){
                    sum++;
                }
                conn_ctr++;
            }
        }
        state_out_ptr = (state_out->data + i*state_out->strides[0]);
        if (conn_ctr < sum*2){
            *state_out_ptr =  true;
        }
        else {
            *state_out_ptr =  false;
        }
}