ctypes in python failed to honor c_int

Jerry Fleming jerry.fleming at saybot.com
Tue Mar 18 21:00:20 EDT 2008


Gabriel Genellina wrote:
> On 18 mar, 04:12, Jerry Fleming <jerry.flem... at saybot.com> wrote:
>> Gabriel Genellina wrote:
>>> On 17 mar, 23:57, Jerry Fleming <jerry.flem... at saybot.com> wrote:
>>>> I have a binary file written with c structures. Each record contains a
>>>> null-terminated string followed by two 4-bytes integers. I wrote a small
>>>> segment of python code to parse this file in this way:
>>>> [coe]
>>>> #!/usr/bin/python
>>>> from ctypes import *
>>>> class Entry(Structure):
>>>>         _fields_ = ('w', c_char_p), ('s', c_uint, 32), ('l', c_uint, 32)
>>>> idx = open('x.idx', 'rb')
>>>> str = idx.read(1000)
>>>> obj = Entry(str)
>>>> print obj.w
>>>> print obj.s
>>>> print obj.l
>>>> [/code]
>>>> where the field w is the string, and s and l are the integers. Problem
>>>> is that, I can only get the strings, not the integers. Well, I did got
>>>> integers, but they are all zeros. What should I do to get the real numbers?
>>> So the string has a variable length? For "Hello" you have
>>> 'h','e','l','l','o', a zero byte, followed by the two integers? This
>>> is somewhat unusual for a C struct (in fact you can't declare it in
>>> C). Perhaps the string is actually a char[n] array with a declared
>>> maximum size?
>> Yes, it has a variable length. The C version of the structure is
>> something like this:
>> [code]
>> struct entry {
>>      char *str,
>>      int start,
>>      int length}
>>
>> [/code]
> 
> But this doesn't match the file contents. There are no pointers in the
> file.
> 
>> And adding repr() would print something like this:
>> [code]
>> '(as) mad as a
>> hatter\x00\x00\x00\x00\x00\x00\x00\x00\x1f-ish\x00\x00\x00\x00\x1f\x00\x00\­x00 at -ism\x00\x00\x00\x00_\x00\x00\x00B-ist\x00\x00\x00\x00\xa1\x00\x00\x00J­.AU\x00\x00\x00\x00\xeb\x00\x00\x00P.EXE\x00\x00\x00\x01;\x00\x00\x00`.GIF\­x00\x00\x00'
>> (as) mad as a hatter
>> 0
>> 0
>> [/code]
>> where the first line is the result of repr(). We can find that, after
>> the null-terminated string '(as) mad as a hatter', there are two
>> integers, 0 and 31 (0x1f). But python treat 31 as zero.
> 
> Ah, but it doesn't "treat 31 as zero". Entry(str) is the same as
> Entry(w=str), that is, you are initializing the w attribute alone,
> leaving the other two integers as 0.
> I don't know how to use ctypes to read the structure (nor if it is
> possible at all), I would read it normally with Python code and build
> the struct afterwards (in case it is used to call any C code).
> 
> w, data = data.split('\x00', 1)
> s, l = struct.unpack("ll", data[:8])
> data= data[8:]
> 
> --
> Gabriel Genellina
Oh yes. What an idiot I am. Thanks Gabriel very much.



More information about the Python-list mailing list