Sequence Protocol, assign item

T

Torsten Mohr

Hi everybody,

at the moment i try to write an extension module in C
and i implement the sequence protocol for the data type
i created. Reading values works fine.

But assigning a value does not work correctly, has anybody
got an example for that?

The function type i have to create is intobjargproc, so
i need to return an "int". Returning 0 or 1 does not seem
to work.

What can the return value be, what can i return her in case
of failure and in case od success?

I don't use any INCREF or DECREF inside my function, do i need
to do that for some parameters? The exact error message i
don't have available at the moment, i'll bring that one tomorrow,
but it looks to me that at the cleanup at the end of the script
an exception is thrown somewhere.


Best regards,
Torsten.
 
M

Michael Hudson

Torsten Mohr said:
Hi everybody,

at the moment i try to write an extension module in C
and i implement the sequence protocol for the data type
i created. Reading values works fine.

But assigning a value does not work correctly, has anybody
got an example for that?

The function type i have to create is intobjargproc, so
i need to return an "int". Returning 0 or 1 does not seem
to work.

What can the return value be, what can i return her in case
of failure and in case od success?

I don't use any INCREF or DECREF inside my function, do i need
to do that for some parameters? The exact error message i
don't have available at the moment, i'll bring that one tomorrow,
but it looks to me that at the cleanup at the end of the script
an exception is thrown somewhere.

I suggest you look at the implementation of, say, lists in the Python
source distribution (Objects/listobject.c).

This is another way of saying I don't remember the answer to your
question :)

Cheers,
mwh
 
T

Torsten Mohr

Hi,

thanks for that hint. I already tried to get some hints from the sources
but at another place.

A) How it is done in Objects/listobject.c:

static int
list_ass_item(PyListObject *a, int i, PyObject *v)
{
PyObject *old_value;
if (i < 0 || i >= a->ob_size) {
PyErr_SetString(PyExc_IndexError,
"list assignment index out of range");
return -1;
}
if (v == NULL)
return list_ass_slice(a, i, i+1, v);
Py_INCREF(v);
old_value = a->ob_item;
a->ob_item = v;
Py_DECREF(old_value);
return 0;
}

B) How i do it:

static int pytypeseq_ass_item(PyObject* s, int nr, PyObject* val) {
int v;
pytype_obj* self = (pytype_obj*)s;

if(!PyArg_ParseTuple(val, "i", &v)) {
return 0;
}

self->msg.d[nr] = v;
/* if(nr > dlc && nr < 8) dlc = nr; */

return 0;
}

In part A some INCREF/DECREF stuff is done, but i think i don't need
this as the PyObjects are only temporarily.

In the test script i use this:
#! /usr/bin/python

from pytype import *

m = PyType();
m.setContent(17, 22, 13);

print m[0], m[1], m[2];

m[0] = 12;

print m[0], m[1], m[2];


When i do it like this, i get:
C:\home\vc++\type\python>qwe.py
Exception exceptions.SystemError: 'new style getargs format but argument \
is not a tuple' in 'garbage collection' ignored

Fatal Python error: unexpected exception during garbage collection

#abnormal program termination


When i delete the line "m[0] = 12;" i do NOT get this error.


I don't really know what this message means, i think i don't correctly
handle the internal data structures somehow.

Has anybody got a hint for me?


Thanks,
Torsten.
 
G

greg

Torsten said:
static int pytypeseq_ass_item(PyObject* s, int nr, PyObject* val) {
int v;
pytype_obj* self = (pytype_obj*)s;

if(!PyArg_ParseTuple(val, "i", &v)) {

You don't want to use PyArg_ParseTuple here, because 'val'
isn't wrapped in a tuple, it's the bare value of the RHS.
Instead you want

v = PyInt_AsLong(val);
if (PyErr_Occurred())
return -1;

Also note the -1 return value (not 0) to signal an error.
In part A some INCREF/DECREF stuff is done, but i think i don't need
this as the PyObjects are only temporarily.

That's correct in this case.
Exception exceptions.SystemError: 'new style getargs format but argument \
is not a tuple' in 'garbage collection' ignored

That's because you were passing PyArg_ParseTuple something
that wasn't a tuple. (The error message talks about argument
formats because PyArg_ParseTuple is intended for processing
argument lists, and in normal use it can't ever get passed
anything other than a tuple.)

Greg
 
T

Torsten Mohr

Hi,

thanks for your answer!
You don't want to use PyArg_ParseTuple here, because 'val'
isn't wrapped in a tuple, it's the bare value of the RHS.
Instead you want

v = PyInt_AsLong(val);
if (PyErr_Occurred())
return -1;

That exactly solves the problem.
Also note the -1 return value (not 0) to signal an error.

I also found this by looking into the sources of Objects/listobject.c,
thanks for that other hint.
That's correct in this case.


That's because you were passing PyArg_ParseTuple something
that wasn't a tuple. (The error message talks about argument
formats because PyArg_ParseTuple is intended for processing
argument lists, and in normal use it can't ever get passed
anything other than a tuple.)

Thanks for your hint, that helped me fix the problem. But where
can i learn more about the internals? Maybe i just assumed this
as a Py_Object* always needed to be transformed the way i did
before.
I did not find any help regarding this in the documentation and also
in the sources it was not obvious to me.


Best regards,
Torsten.
 

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

No members online now.

Forum statistics

Threads
474,156
Messages
2,570,878
Members
47,404
Latest member
PerryRutt

Latest Threads

Top