C API String Parsing/Returning

Gerhard Häring gh at ghaering.de
Mon Apr 6 08:57:01 EDT 2009


k3xji wrote:
> Hi all,
> 
> This might be a newbie question. I am trying to implement a simple
> string decoder/encoder algorithm. Just suppose I am substrcating some
> values from the string passed as a parameter to the function and I
> want the function to return encoded/decoded version of the string.
> 
> Here is the call:
> ss= esauth.penc('s')
> st = esauth.pdec(ss)
> 
> static PyObject *
> pdec(PyObject *self, PyObject *args)
> {
> 	unsigned char *s= NULL;
> 
> 	unsigned int v,len,i = 0;
> 
> 	if (!PyArg_ParseTuple(args, "s", &s))
>         return NULL;

> 	if (!s)
> 		return NULL;

These two lines are superfluous. s now points to the contents of the
Python string (which must not contain any 0 characters, else a TypeError
is raised instead). Python strings are immutable, so you should *not
modify this C string*.

> 	len = strlen(s);
> 
> 	for(i=0;i<len;i++) {
>                 if (s[i] > 10)
> 		    s[i] = s[i] - 10;
> 	}
> 
> 	return Py_BuildValue("s",s);
> }
> 
> 
> This is returning the original string. I mean the parameter is changed
> but the Py_BuildValue is returning the original string passed in as
> param. [...]

Yes, that's because you're returning a Python string from the string
passed in ;-)

You should do something else instead:

char* buf = strdup(s);
if (!buf) {
    PyErr_SetString(PyExc_MemoryError, "Out of memory: strdup failed");
    return NULL;
}

/* TODO: your string manipulation */

return PyString_FromString(buf); /* return Py_BuildValue("s", buf); */

If you want to cope with Python strings that may contain 0 bytes, parse
them with "s#" instead. This should normally be better because you avoid
the strlen() this way.

HTH

-- Gerhard




More information about the Python-list mailing list