我在for循环中有一个if子句,我在其中预先定义了state_out:
state_out = (PyArrayObject *) PyArray_FromDims(1,dims_new,NPY_BOOL);
if条件是这样的:
if (conn_ctr<sum*2){
*(state_out->data + i*state_out->strides[0]) = true;
}
else {
*(state_out->data + i*state_out->strides[0]) = false;
}
当评论这些时,state_out返回一个全错误的Numpy数组。我没看到这个任务有问题。据我所知,在此代码中调用的结构PyArrayObject中的所有内容都是指针,因此在指针运算之后,它应该指向我打算写入的地址。 (如果代码中的条件是通过以这种方式达到值来构建的,并且我知道它有效,因为我设法打印输入数组的值。)然后,如果我想将bool分配给内存中的其中一个部分,我应该通过*(pointer_intended) = true
分配它。我错过了什么?
编辑:我发现,即使我将一些printf函数放入其中,即使我没有达到这些值:
if (conn_ctr<sum*2){
printf("True!\n");
}
else {
printf("False!\n");
}
我再次获得了SegFault。
非常感谢,其余的代码就在这里。
#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);
}
答案 0 :(得分:0)
if (conn_ctr<sum*2){
*(state_out->data + i*state_out->strides[0]) = true;
}
else {
*(state_out->data + i*state_out->strides[0]) = false;
}
在这里,我天真地做一个指针算术,state_out-&gt; data是一个指向数据开头的指针,它被定义为char的指针:SciPy Doc - Python Types and C-Structures
typedef struct PyArrayObject {
PyObject_HEAD
char *data;
int nd;
npy_intp *dimensions;
npy_intp *strides;
...
} PyArrayObject;
我在这里复制了哪一部分。 state_out-&gt; strides是指向我们所拥有的数组维度长度数组的指针。在这种情况下,这是一个1d数组。所以,当我做指针算术(state_out->data + i*state_out->strides[0])
时,我当然的目的是计算指向数组的第i个值的指针,但是我没有给出指针的类型,所以
我曾尝试过:
NPY_BOOL *adj_value_ptr, *mask_value_ptr, *state_value_ptr, *state_out_ptr;
变量指向我对for循环感兴趣的值,而state_out_ptr是我写的那个。我曾经想过,因为我说的是
这些数组的成分是NPY_BOOL
类型,指向数组中数据的指针也是NPY_BOOL
类型的指针。 当使用直接操作内存的数据时,SegFault失败。这是因为NPY_BOOL是一个整数的enum
(在评论中可以说是pv).NumPy可以在内部使用,。顺序有一个C typedef
npy_bool
在代码中使用布尔值。 Scipy Docs。当我介绍类型为
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;
}
}