Hi all,
I have been working on writing a class in C for a Python game I am developing. The game uses Pygame and Numpy. Currently, I am adding a function to the class to take a 3D array (numpy/arrayobject, as is returned by pygame.surfarray.pixels3d), alter some of the rgb pixel values, and return a resulting 3D array.
Right now, this code looks like...
I have a number of print statements to help me with the debug.
Now, to the error that I am having...
By following the debug statements, I have found that I am SOMETIMES getting a segmentation fault upon the return line (return final; ) for TileTransform_getTransformedTile. I say sometimes because there are multiple cases (at least one of them being identical) that successfully use this function without the fault.
I am also unsure of whether the Py_DECREF is necessary with the array, but that is a secondary concern until the return statement issue is solved. I have tried the program with and without the DECREF and still have the segmentation fault in the same place.
In case it helps, here is the output when I run the game....
Some of the output is from the class' debug, but the # # [#, #, #, #] is from the game itself and represents: x y [topology of corners relative to the world].
Any ideas regarding the issue are greatly appreciated (as are suggestions for cleaning-up the code... C is not my specialty )
Thanks!
~Tale
I have been working on writing a class in C for a Python game I am developing. The game uses Pygame and Numpy. Currently, I am adding a function to the class to take a 3D array (numpy/arrayobject, as is returned by pygame.surfarray.pixels3d), alter some of the rgb pixel values, and return a resulting 3D array.
Right now, this code looks like...
Code:
static PyArrayObject *
backSingle(TileTransform *self, PyArrayObject *source)
{
PyArrayObject *result;
int dimensions[3];
int column, row;
printf("Variables initialized.\n");
dimensions[0] = self->width;
dimensions[1] = self->halfLength;
dimensions[2] = 3;
result = (PyArrayObject *)PyArray_FromDims(3, dimensions, PyArray_INT);
printf("Result made.\n");
for (column = 0; column < self->width; column++)
{
for (row = 0; row < self->length; row++)
{
//Get the color.
int red = *(int *)(source->data + column*source->strides[0] + row*source->strides[1]);
int green = *(int *)(source->data + column*source->strides[0] + row*source->strides[1] + source->strides[2]);
int blue = *(int *)(source->data + column*source->strides[0] + row*source->strides[1] + 2*source->strides[2]);
//Alter the row value.
int newRow = row/2;
//Alter the color.
//Save the new color.
source->data[column*source->strides[0] + row*source->strides[1]] = red;
source->data[column*source->strides[0] + row*source->strides[1] + source->strides[2]] = green;
source->data[column*source->strides[0] + row*source->strides[1] + 2*source->strides[2]] = blue;
}
}
return result;
}
static char TileTransform_getTransformedTile_doc[] =
"Get the transformed tile from the provided tile and topology. The topology must be a list with 4 elements with values of 0, 1 or 2, \
the first element is the top of the tile, the second is the left corner, the third is the right corner, and the fourth is the bottom \
corner. The provided tile is to be given as a 3D array of rgb values.";
static PyObject *
TileTransform_getTransformedTile(TileTransform *self, PyObject *args)
{
PyObject *source;
PyObject *final;
PyArrayObject *sourceArray;
PyArrayObject *resultArray;
PyObject *topology;
int top, left, right, bottom, topologyValue;
//Parse the input parameters.
if (! PyArg_ParseTuple(args, "OO", &source, &topology))
return NULL;
top = PyLong_AsLong(PyList_GetItem(topology, 0));
left = PyLong_AsLong(PyList_GetItem(topology, 1));
right = PyLong_AsLong(PyList_GetItem(topology, 2));
bottom = PyLong_AsLong(PyList_GetItem(topology, 3));
topologyValue = TOP_PRIME*top + LEFT_PRIME*left + RIGHT_PRIME*right + BOTTOM_PRIME*bottom;
//Return if this tile has no changes to be made or is a cliff.
if (topologyValue == NO_TOPOLOGY_CHANGE || top == 2 || left == 2 || right == 2 || bottom == 2)
return source;
//Translate the source to an array.
printf("Translating source to array.\n");
sourceArray = (PyArrayObject *) PyArray_ContiguousFromObject(source, PyArray_LONG, 0, 3);
printf("Checking source array.\n");
if (sourceArray->nd != 3 || sourceArray->descr->type_num != PyArray_LONG)
{
//Py_DECREF(sourceArray);
PyErr_SetString(PyExc_ValueError, "Array must be three-dimensional and of type int");
return NULL;
}
if (sourceArray->dimensions[0] != self->width || sourceArray->dimensions[1] != self->length)
{
//Py_DECREF(sourceArray);
PyErr_SetString(PyExc_ValueError,
"Array width and length must match the width and length provided to the Tile Transform constructor.");
return NULL;
}
if (sourceArray->dimensions[2] != 3)
{
//Py_DECREF(sourceArray);
PyErr_SetString(PyExc_ValueError,
"Array must be three-dimensional and with the highest dimension containing 3 integers (rgb values).");
return NULL;
}
//Execute the appropriate function.
if (topologyValue == BACK_SINGLE)
{
printf("Back Single Transformation Call\n");
resultArray = backSingle(self, sourceArray);
}
else
{
//Py_DECREF(sourceArray);
return source;
}
printf("Topology: %d %d %d %d; %d\n", top, left, right, bottom, topologyValue);
//Py_DECREF(sourceArray);
printf("Preparing Final\n");
final = PyArray_Return(resultArray);
printf("Returning Final\n");
return final;
}
I have a number of print statements to help me with the debug.
Now, to the error that I am having...
By following the debug statements, I have found that I am SOMETIMES getting a segmentation fault upon the return line (return final; ) for TileTransform_getTransformedTile. I say sometimes because there are multiple cases (at least one of them being identical) that successfully use this function without the fault.
I am also unsure of whether the Py_DECREF is necessary with the array, but that is a secondary concern until the return statement issue is solved. I have tried the program with and without the DECREF and still have the segmentation fault in the same place.
In case it helps, here is the output when I run the game....
Code:
429 1668 [25, 25, 25, 25]
429 1669 [25, 25, 25, 25]
429 1670 [25, 25, 25, 25]
429 1671 [25, 25, 25, 25]
429 1672 [25, 25, 25, 25]
429 1673 [25, 25, 25, 26]
Translating source to array.
Checking source array.
Back Single Transformation Call
Variables initialized.
Result made.
Topology: 0 0 0 1; 11
Preparing Final
Returning Final
429 1674 [25, 25, 26, 26]
Translating source to array.
Checking source array.
429 1675 [26, 26, 26, 26]
429 1676 [26, 26, 26, 26]
429 1677 [26, 26, 26, 27]
Translating source to array.
Checking source array.
Back Single Transformation Call
Variables initialized.
Result made.
Topology: 0 0 0 1; 11
Preparing Final
Returning Final
429 1678 [26, 26, 27, 26]
Translating source to array.
Checking source array.
429 1679 [27, 26, 27, 27]
Translating source to array.
Checking source array.
429 1680 [26, 27, 27, 27]
Translating source to array.
Checking source array.
429 1681 [27, 27, 27, 26]
Translating source to array.
Checking source array.
429 1682 [27, 27, 26, 27]
Translating source to array.
Checking source array.
429 1683 [26, 27, 26, 27]
Translating source to array.
Checking source array.
429 1684 [27, 27, 27, 27]
429 1685 [27, 27, 27, 27]
429 1686 [27, 27, 27, 27]
429 1687 [27, 27, 27, 27]
429 1688 [27, 27, 27, 26]
Translating source to array.
Checking source array.
429 1689 [27, 26, 26, 26]
Translating source to array.
Checking source array.
429 1690 [26, 26, 26, 26]
429 1691 [26, 26, 26, 26]
429 1692 [26, 26, 26, 26]
429 1693 [26, 26, 26, 25]
Translating source to array.
Checking source array.
429 1694 [26, 25, 25, 25]
Translating source to array.
Checking source array.
430 1668 [25, 25, 25, 25]
430 1669 [25, 25, 25, 25]
430 1670 [25, 25, 25, 25]
430 1671 [25, 25, 25, 25]
430 1672 [25, 25, 25, 25]
430 1673 [25, 25, 26, 26]
Translating source to array.
Checking source array.
430 1674 [25, 26, 26, 26]
Translating source to array.
Checking source array.
430 1675 [26, 26, 26, 26]
430 1676 [26, 26, 26, 26]
430 1677 [26, 26, 27, 27]
Translating source to array.
Checking source array.
430 1678 [26, 27, 27, 27]
Translating source to array.
Checking source array.
430 1679 [27, 27, 27, 27]
430 1680 [27, 27, 27, 27]
430 1681 [27, 27, 27, 26]
Translating source to array.
Checking source array.
430 1682 [27, 26, 26, 26]
Translating source to array.
Checking source array.
430 1683 [26, 26, 26, 27]
Translating source to array.
Checking source array.
Back Single Transformation Call
Variables initialized.
Result made.
Topology: 0 0 0 1; 11
Preparing Final
Returning Final
430 1684 [26, 27, 27, 27]
Translating source to array.
Checking source array.
430 1685 [27, 27, 27, 27]
430 1686 [27, 27, 27, 27]
430 1687 [27, 27, 27, 27]
430 1688 [27, 27, 27, 26]
Translating source to array.
Checking source array.
430 1689 [27, 26, 27, 26]
Translating source to array.
Checking source array.
430 1690 [26, 26, 26, 26]
430 1691 [26, 26, 26, 26]
430 1692 [26, 26, 26, 26]
430 1693 [26, 26, 26, 26]
430 1694 [26, 25, 26, 25]
Translating source to array.
Checking source array.
431 1668 [25, 25, 25, 25]
431 1669 [25, 25, 25, 25]
431 1670 [25, 25, 25, 25]
431 1671 [25, 25, 25, 25]
431 1672 [25, 25, 25, 26]
Translating source to array.
Checking source array.
Back Single Transformation Call
Variables initialized.
Result made.
Topology: 0 0 0 1; 11
Preparing Final
Returning Final
Fatal Python error: (pygame parachute) Segmentation Fault
This application has requested the Runtime to terminate it in an unu
Please contact the application's support team for more information.
Some of the output is from the class' debug, but the # # [#, #, #, #] is from the game itself and represents: x y [topology of corners relative to the world].
Any ideas regarding the issue are greatly appreciated (as are suggestions for cleaning-up the code... C is not my specialty )
Thanks!
~Tale