简体   繁体   中英

python C extension of numpy error in 64-bit centos, but Ok in 32-bit centos

It's supposed to be called like this:

Pyentropy(np.array([1,2,2,1,1,1],int), 0)

or

Pyentropy(np.array([1,2,2,1,1,1],int), 1)

It meant to calculate the entropy of [1,2,2,1,1,1] But in Pyentropy, [1,2,2,1,1,1] is converted to a C-array and call entropy to calculate entropy with this C-array

A problem occurs in the process of converting array to C-array. In fedora 19(32-bit Python2.7), nothing wrong. But in CentOS 6.5(final 64-bit Python 2.6), I have recompiled with python2.6. Once called in CentOS, the entropy was wrong. I have printed the array and the C-array, however, it's different. Obviously, the conversion is wrong in CentOS(64-bit), But where is the problem? I have revised the code many times, the problem is still there.

static PyObject *Pyentropy(PyObject *self, PyObject *args){
    PyObject *xobj;
    int ng;
    int *x;
    int *xc;
    int i;
    double ntrp;
    if (!PyArg_ParseTuple(args, "Oi", &xobj, &ng))
        return NULL;
    npy_intp dims;
    int nd = 1;
    PyArray_Descr *descr = PyArray_DescrFromType(NPY_INT64);
    if(PyArray_AsCArray(&xobj,(void*)&x,&dims,nd,descr) < 0){
        PyErr_SetString(PyExc_TypeError, "error converting to C array");
        return NULL;
    }
    xc = calloc(dims, sizeof(int));
    for (i=0; i<dims; i++){
        xc[i] = x[i];
    }
    /*ununified*/
    ntrp = entropy(xc,dims,ng);
    free(xc);
    return Py_BuildValue("d",ntrp);
}

I think the issue is with the type of x . After the call to PyArray_AsCArray , it is pointing to a data segment of NPY_INT64 s with the data from xobj . If on your platform int (the type of x ) is the same as npy_int64 , your program will run without problems. But if your int s are 32 bit integers, then you will be accessing the memory incorrectly, and probably have a lot of zeros alternating with only the first half of the values in your array.

Try the following changes to your function:

npy_int64 *x;

...

for (i = 0; i < dims; i++) {
    xc[i] = (int)x[i];
}

It is not the most efficient of ways to get this done, but I think it will work for your case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM