c-extension crashes unexpected

M

Markus Wintermann

hello,

i try to write an extension which calls an api.
however,
i haven´t written very much till now,
but i`ve already managed to make a mistake.

because when i try to call my function,
python 2.4 dies with an errorwindow.

i believe that has something todo with reference counts and memory
allocation but i can´t find my mistake.

here´s the code:

/* Wrapper-Funktion für apiJob() */
static PyObject* wrap_apiJob(PyObject* self, PyObject* args) {

char* ecu = (char *) PyMem_Malloc(APIMAXNAME);
char* job = (char *) PyMem_Malloc(APIMAXNAME);
char* para = (char *) PyMem_Malloc(APIMAXPARA);
PyObject *resultlist;
unsigned short i,j,setcount,resultcount;

if (!PyArg_ParseTuple(args, "ss|s", &ecu, &job, &para)) { return 0;}

if (!apiInit()) return Py_BuildValue("s", apiErrorText());

apiJob(ecu, job, para, "");

while (apiState()==APIBUSY);

if (apiState()==APIERROR) {
return Py_BuildValue("s", apiErrorText());
}

if (!apiResultSets(&setcount)) return Py_BuildValue("s",
apiErrorText());

for (i=0;i<setcount+1;i++) {
PyList_SetItem(resultlist, i, Py_BuildValue("i",i));

}

resultlist = PyList_New(setcount+1);


PyMem_Free(ecu);
PyMem_Free(job);
PyMem_Free(para);

return Py_BuildValue("N",resultlist);
}
 
J

John Machin

hello,

i try to write an extension which calls an api.
however,
i haven´t written very much till now,
but i`ve already managed to make a mistake.

because when i try to call my function,
python 2.4 dies with an errorwindow.

i believe that has something todo with reference counts and memory
allocation but i can´t find my mistake.

here´s the code:

/* Wrapper-Funktion für apiJob() */
static PyObject* wrap_apiJob(PyObject* self, PyObject* args) {

PyObject *resultlist;
unsigned short i,j,setcount,resultcount;

for (i=0;i<setcount+1;i++) {
PyList_SetItem(resultlist, i, Py_BuildValue("i",i));

Thomas has already shown you where your particular bug is. However you
have a general problem. Look at the documentation for PyList_SetItem
and Py_BuildValue:
"""
int PyList_SetItem( PyObject *list, int index, PyObject *item)

Sets the item at index index in list to item. Returns 0 on success or
-1 on failure. Note: This function ``steals'' a reference to item and
discards a reference to an item already in the list at the affected
position.

PyObject* Py_BuildValue( char *format, ...)

Return value: New reference.
Create a new value based on a format string similar to those accepted
by the PyArg_Parse*() family of functions and a sequence of values.
Returns the value or NULL in the case of an error; an exception will
be raised if NULL is returned. <snip>
"""

You are not testing for errors after PyBlahBlah() function calls.

The last line of your code that I quoted above should be replaced by
something like this:

val = Py_BuildValue("i",i);
if (val == NULL) BOGOFF(1);
if PyList_SetItem(resultlist, i, val) BOGOFF(2);

where BOGOFF(n) is a #define that prints something like "Problem n in
<myfunc>" if you are in debug mode, and then does a "goto cleanup"
where you release resources and return NULL;

This testing (and the following purist-horrifying "goto" to get to
your clean-up block) is an unfortunate but necessary part of using the
Python C API.

Some suggestions:

1. Try Pyrex. You get to write in a higher-level language and it does
all the boring ugly error-prone stuff for you -- this includes
reference counting as well! Look at the C code that Pyrex generates,
to see what Pyrex is saving you from.
2. If you still insist on DIY, look at some of the Python source code
in the Modules and Objects directories to see how it is done.
3. Examine carefully the book or whatever you have been learning from.
If it doesn't cover topics like always checking for errors, throw it
in the garbage bin (and tell the world via this newsgroup). If it does
cover such topics but you've been ignoring it, well then, it's up to
you what you do next :)

HTH,
John
 
M

Markus Wintermann

John said:
...

Some suggestions:

1. Try Pyrex. You get to write in a higher-level language and it does
all the boring ugly error-prone stuff for you -- this includes
reference counting as well! Look at the C code that Pyrex generates,
to see what Pyrex is saving you from.
2. If you still insist on DIY, look at some of the Python source code
in the Modules and Objects directories to see how it is done.
3. Examine carefully the book or whatever you have been learning from.
If it doesn't cover topics like always checking for errors, throw it
in the garbage bin (and tell the world via this newsgroup). If it does
cover such topics but you've been ignoring it, well then, it's up to
you what you do next :)

HTH,
John

many thanks.

it works now, but i´ll try to do the whole thing with pyrex.
because i´m not so familiar with error handling.
i tried to write this with some tutorials and there is always written
something like:
"i know it´s no nice style to have no errorhandling but for excercise
purpose that´s not necessary."
and i never know what to add.
luckily now the good pyrex will do this for me,
if i get it to work.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top