抱歉,如果这个问题有点含糊,可能根本不适合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; }