Python中的C(cpp)扩展在一台机器上工作,但在另一台机器上不工作
很抱歉,如果这个问题有点模糊,可能根本不适合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上无法运行。它的构建/安装似乎很好,但当我实际尝试运行它时,它会给我一个特定的错误:Python中的C(cpp)扩展在一台机器上工作,但在另一台机器上不工作,python,Python,很抱歉,如果这个问题有点模糊,可能根本不适合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上无法运行。它的构建/安装似乎很好,但当我实际尝试运行它时,它会给我一个特定的错误: TypeEr
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();
}
我无法在这台机器上更新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 1d:public JPythonArray
{
公众:
JPythonArray1D(PyArrayObject*init):JPythonArray(init,1){
JPythonArray1D(PyObject*init):JPythonArray(init,1){}
JPythonArray1D(类型*inData,npy_intp*inDims,npy_intp*inStrides):JPythonArray(inData,1,inDims,inStrides){}
Type&operator[](int i)//注意,我们在这里返回一个引用,因此它可以用作左值,例如my1DArray[0]=1.0或my2DArray[0][0]=1.0;
{
//printf(“访问元素%d,共%d\n”,i,JPythonArray::dims[0]);
总是断言(i
以及完整的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; }
#包括“JPythonArray.h”
模板int数组类型(void){return NPY_DOUBLE;}
模板int数组类型(void){return NPY_FLOAT;}
模板int数组类型(void){return NPY_int;}
<代码>你在两台机器上都使用相同的Python和NoMPy版本吗?我可能错了,但是你似乎在C++代码>外部的“C”< /Cuth>块中使用C++语法(模板语法)。不知道这是不是个好主意。(您首先是如何构建扩展的?)。我编辑了这个问题,但也将它复制到了这里:13.04 Lubuntu和GCC4.7.3、python 2.7.4、Numpy1.7.1,但在12.04 Ubuntu和GCC4.6.3、python 2.7.3、Numpy1.6.1的另一台机器上不起作用。我只运行以下命令:python setup.py build;python setup.py安装并有一个文件夹构建,与.cpp和.h文件共用…但我怀疑这是你问我如何构建扩展的问题。你应该能够看到在运行setup.py build
时是否使用了gcc或g++。此外,是<代码> JPythNalay2D2>代码>确实是一个C++模板?每当我得到一个错误(如果我修改了什么),它就说是GCC错误。否则,它在运行时不会显示在任何位置。有趣的是,我只有JPythonArray.h和.cpp,但在其中他们提到了JPythonArray2D(我不熟悉cpp,我是由其他人编写的代码,我在原始问题中添加了.h文件中可能相关的部分)。你认为代码是问题所在吗(即C、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; }