How does cffi deal with with null terminated C strings Vs python strings that are not nul terminated

722 views
Skip to first unread message

Sarvi Shanmugham

unread,
Nov 14, 2012, 1:36:07 PM11/14/12
to pytho...@googlegroups.com
While working with NETLINK sockets I discovered a nuance that I had to deal with when working with C libraries

when netlink socket get a data packed as C structure, that contains strings, and I use the python "struct" module to 
extract data, the string I get is a null terminated string as a python string.

For example, the inter face name field when extracted to a python string variable would contain 'eth0\0'
If I try to compare it with 'eth0' they obviously don't match. 
Because python does not use null terminated strings, and instead maintains the string length.
Obviously this can be addressed by a strip('\0')

But it raised a question of how CFFI deals with it when passing string arguments between python/clibrary and back?

Is the null termination stripped/added?

Sarvi

Armin Rigo

unread,
Nov 15, 2012, 4:11:42 PM11/15/12
to pytho...@googlegroups.com
Hi Sarvi,

On Wed, Nov 14, 2012 at 7:36 PM, Sarvi Shanmugham <sarv...@gmail.com> wrote:
> But it raised a question of how CFFI deals with it when passing string
> arguments between python/clibrary and back?
>
> Is the null termination stripped/added?

When you pass a Python object as a "TYPE *" argument to a CFFI
function, it can be either a CFFI pointer object whose type is already
"TYPE *" or "TYPE[]", or else a Python object that will be converted
to a "TYPE[]". So in case it is a Python string passed to a "char *"
argument, the conversion is to "char[]". You get the same object as
ffi.new("char[]", "hello") --- which means you get an extra \0.

A return value of type "char *" is never automatically converted to a
Python string. You need to call ffi.string(). This will convert the
string until the first null character, not included.

If you read some field of a structure declared as an array of chars,
and call ffi.string() on it, then CFFI knows the length and uses it as
an upper bound. It still stops at the first \0, if any. In other
words ffi.string() never returns a \0 character.

To convert a char*-and-length pair to a Python string that may contain
\0, you need ffi.buffer(charp, length)[:].


A bientôt,

Armin.
Reply all
Reply to author
Forward
0 new messages