3

抱歉,如果这个问题有点含糊,可能根本不适合stackoverflow,但我只是试一试,也许有人会知道可能是什么原因或给出测试方法,问题出在哪里是。

我有一个 C (cpp?) 扩展,它在我的 13.04 Lubuntu 和 gcc 4.7.3、python 2.7.4、numpy 1.7.1 上工作正常,但在 12.04 Ubuntu 和 gcc 4.6.3、python 2.7.3、numpy 上不能工作1.6.1 在另一台机器上。它似乎构建/安装很好,但是当我真正尝试运行这个东西时,它给了我一个特定的错误:

TypeError: Array type 7 didn't match expected type -1

我不想用构建代码向您发送垃圾邮件,但我将包括两个代码,我认为这是主要的。首先是cpp文件

    #define PY_ARRAY_UNIQUE_SYMBOL j_sad_pyarray
    #include "Common/JAssert.h"
    #include "Python.h"
    #include "numpy/arrayobject.h"
    #include "Common/JPythonCommon.h"

    extern "C" PyObject *sad_correlation(PyObject *self, PyObject *args)
    {
        // inputs
        PyArrayObject *a, *b;       // list of coordinates for the input polygons (2d double numpy array)

        // parse the input arrays from *args
        if (!PyArg_ParseTuple(args, "O!O!", 
                &PyArray_Type, &a, 
                &PyArray_Type, &b))
        {
            PyErr_Format(PyErr_NewException((char*)"exceptions.TypeError", NULL, NULL), "Unable to parse array!");
            return NULL;
        }

        // We expect a and b to be two-dimensional double arrays.
        // The following constructors will check those requirements
        JPythonArray2D<double> window1(a);
        JPythonArray2D<double> window2(b);
        if (PyErr_Occurred()) return NULL;

    //  ALWAYS_ASSERT(window1.NDims() == 2);
    //  ALWAYS_ASSERT(window2.NDims() == 2);
        if ((window1.NDims() != 2) || (window1.NDims() != 2))
        {
            PyErr_Format(PyErr_NewException((char*)"exceptions.TypeError", NULL, NULL), "Expected two 2D arrays as parameters");
            return NULL;
        }

        int maxDX = window2.Dims()[0] - window1.Dims()[0];
        int maxDY = window2.Dims()[1] - window1.Dims()[1];
    //  ALWAYS_ASSERT(maxDX >= 0);
    //  ALWAYS_ASSERT(maxDY >= 0);
        if ((maxDX < 0) || (maxDY < 0))
        {
            PyErr_Format(PyErr_NewException((char*)"exceptions.TypeError", NULL, NULL), "Expected second array to be bigger than or equal to first array");
            return NULL;
        }

        npy_intp output_dims[2] = { maxDX+1, maxDY+1 };
        PyArrayObject *result = (PyArrayObject *)PyArray_SimpleNew(2, output_dims, NPY_DOUBLE);
        JPythonArray2D<double> resultArray(result);

        // For every possible shift of 'a' relative to 'b', calculate the SAD
    //  printf("Array sizes %ldx%ld, %ldx%ld\n", window1.Dims()[0], window1.Dims()[1], window2.Dims()[0], window2.Dims()[1]);
        int w1Width = window1.Dims()[0];
        int w1Height = window1.Dims()[1];
        for (int dy = 0; dy <= maxDY; dy++)
            for (int dx = 0; dx <= maxDX; dx++)
            {
                int sad = 0;
                for (int y = 0; y < w1Height; y++)
                    for (int x = 0; x < w1Width; x++)
                    {
                        // ***** is this the correct way round?
                        ALWAYS_ASSERT(window1[0].Dims()[0] == window1.Dims()[1]);
                        sad += abs(window1[x][y] - window2[x+dx][y+dy]);
                    }
                resultArray[dx][dy] = sad;  
    //          printf("Result[%d][%d] = %d\n", dx, dy, sad);       
            }
        return PyArray_Return(result);
    }


    /* Define a methods table for the module */

    static PyMethodDef corr_methods[] = {
        {"sad_correlation", sad_correlation, METH_VARARGS}, 
        {NULL,NULL} };



    /* initialisation - register the methods with the Python interpreter */

    extern "C" void initj_py_sad_correlation(void)
    {
        (void) Py_InitModule("j_py_sad_correlation", corr_methods);
        import_array();
    }

和 .py 文件:

# Run the following command:
#   python setup.py build; python setup.py install
# in order to compile and install the j_py_sad_correlation module
from j_py_sad_correlation import *
import numpy as N

a = N.random.randint(0, 100, (4,4))
b = N.random.randint(0, 100, (4,4))
print a
print b

sad_using_c_code = sad_correlation(a, b)
print sad_using_c_code

sad_using_python_code = N.zeros((b.shape[0] - a.shape[0] + 1, b.shape[1] - a.shape[1] + 1))
for z in range(sad_using_python_code.shape[1]):
    for q in range(sad_using_python_code.shape[0]):
        sad_using_python_code[q,z] = sum(sum(abs(a - b[q:q+a.shape[0], z:z+a.shape[1]])))
print sad_using_python_code

print "success if these values are both zero:", (sad_using_python_code - sad_using_c_code).max(), (sad_using_python_code - sad_using_c_code).min() 

我无法更新这台机器上的 gcc(无论我做什么,我最终都会得到相同的),你认为这可能是一个问题(即 gcc 版本)吗?有什么方法可以追踪问题吗?

JPythonArray.h 的部分:

template<class Type> class JPythonArray1D : public JPythonArray<Type>
{
  public:
    JPythonArray1D(PyArrayObject *init) : JPythonArray<Type>(init, 1) { }
    JPythonArray1D(PyObject *init) : JPythonArray<Type>(init, 1) { }
    JPythonArray1D(Type *inData, npy_intp *inDims, npy_intp *inStrides) : JPythonArray<Type>(inData, 1, inDims, inStrides) { }

    Type &operator[](int i)     // Note we return a reference here, so that this can be used as an lvalue, e.g. my1DArray[0] = 1.0, or my2DArray[0][0] = 1.0;
    {
//      printf("Access element %d of %d\n", i, JPythonArray<Type>::dims[0]);
        ALWAYS_ASSERT(i < JPythonArray<Type>::dims[0]);
        return JPythonArray<Type>::data[i * JPythonArray<Type>::strides[0]];
    }

    Type &GetIndex_CanPromote(int i)
    {
        // Behaves like operator[], but if we have a single value in the array then returns that value regardless of i
        // This isn't ideal - it's a way of working around the fact that the object used to initialize this array may be a scalar value
        if (JPythonArray<Type>::dims[0] == 1)
            return JPythonArray<Type>::data[0];
        else
            return operator[](i);
    }
};

template<class Type> class JPythonArray2D : public JPythonArray<Type>
{
  public:
    JPythonArray2D(PyArrayObject *init) : JPythonArray<Type>(init, 2) { }
    JPythonArray2D(PyObject *init) : JPythonArray<Type>(init, 2) { }
    JPythonArray2D(Type *inData, npy_intp *inDims, npy_intp *inStrides) : JPythonArray<Type>(inData, 2, inDims, inStrides) { }

    JPythonArray1D<Type> operator[](int i)
    {
        // Could check that i is in range (check against dims[0])
        return JPythonArray1D<Type>(JPythonArray<Type>::data + JPythonArray<Type>::strides[0] * i, JPythonArray<Type>::dims + 1, JPythonArray<Type>::strides + 1);
    }
};

template<class Type> class JPythonArray3D : public JPythonArray<Type>
{
  public:
    JPythonArray3D(PyArrayObject *init) : JPythonArray<Type>(init, 3) { }
    JPythonArray3D(PyObject *init) : JPythonArray<Type>(init, 3) { }

    JPythonArray2D<Type> operator[](int i)
    {
        // Could check that i is in range (check against dims[0])
        return JPythonArray2D<Type>(JPythonArray<Type>::data + JPythonArray<Type>::strides[0] * i, JPythonArray<Type>::dims + 1, JPythonArray<Type>::strides + 1);
    }
};

template<class Type> JPythonArray2D<Type> PromoteTo2D(PyArrayObject *init)
{
    if (PyArray_NDIM(init) == 1)
    {
        npy_intp dims[2] = { 1, PyArray_DIMS(init)[0] };
        npy_intp strides[2] = { 0, PyArray_STRIDES(init)[0] / sizeof(Type) };
        return JPythonArray2D<Type>((Type *)PyArray_DATA(init), dims, strides);
    }
    else
    {
        // This could fail (if for example we are given a 3D array), but if that happens then a suitable error should be reported
        return JPythonArray2D<Type>(init);
    }
}

以及完整的 JPythonArray.cpp:

#include "JPythonArray.h"

template<> int ArrayType<double>(void) { return NPY_DOUBLE; }
template<> int ArrayType<float>(void) { return NPY_FLOAT; }
template<> int ArrayType<int>(void) { return NPY_INT; }
4

0 回答 0