Connecting Tech Pros Worldwide Help | Site Map

A little comments of ctypes and construct.

=?GB2312?B?0rvK18qr?=
Guest
 
Posts: n/a
#1: Nov 21 '08
Hi all,

Recently I asked a question on this group:

Quote:
Quote:
>What's your choice when handle complicated C structures.
I got these suggestion:

1) try construct

2) try ctypes

----------------

I spend half a day on construct and here's my conclusion:

1. It really good for parse(unpack) data structures.

But

1. It's not that good for pack.
2. From the documents and example, can not find out how to describe
nested struct array.

for example:

typedef struct _Point
{
int x;
int y;
} Point;

typedef struct _Shape
{
int z;
Point ap[2];
}Shape;

Can not find out how to describe this..


----------------

Then I tried ctypes.

1. It works fine for pack

BUT:

1. I can not figure out how to unpack. The examples I googled doesn't
work on my computer.

http://markmail.org/message/44tu6rm4nejxgbdd

2. BigEndianStructure can not be nested. So. If you need bid endian,
you got bad luck.

So, both of them are not ideal solution to pack and unpack
sophisticated C style data structures.

----------------

BTW: Some one suggested that I should use struct.Struct and
namedtuple.

I skimmed the document, but can't find a clear way to handle nested
structures.
Aaron Brady
Guest
 
Posts: n/a
#2: Nov 21 '08

re: A little comments of ctypes and construct.


On Nov 21, 2:28 am, 一首诗 <newpt...@gmail.comwrote:
Quote:
Hi all,
>
Recently I asked a question on this group:
>
Quote:
Quote:
What's your choice when handle complicated C structures.
snip
Quote:
>
typedef struct _Point
{
int x;
int y;
>
} Point;
>
typedef struct _Shape
{
int z;
Point ap[2];
>
}Shape;
snip
Quote:
2. BigEndianStructure can not be nested. So. If you need bid endian,
you got bad luck.
A bug is filed about this.

I have this code working:

import ctypes as c
class Point( c.LittleEndianStructure ):
_fields_= [
( 'x', c.c_int ),
( 'y', c.c_int )
]

class Shape( c.LittleEndianStructure ):
_fields_= [
( 'z', c.c_int ),
( 'ap', Point* 2 )
]

lib= c.WinDLL( 'ng36ext.pyd' )
lib.make.argtypes= [ ]
lib.make.restype= Shape
shape= lib.make( )
print shape.z, shape.ap[0].x, shape.ap[0].y, shape.ap[1].x, shape.ap
[1].y

/Output:

10 20 30 40 50
20
10 20 30 40 50

/Definition for 'make':

Shape make( void ) {
Shape shape;
shape.z= 10;
shape.ap[ 0 ].x= 20;
shape.ap[ 0 ].y= 30;
shape.ap[ 1 ].x= 40;
shape.ap[ 1 ].y= 50;
printf( "%i %i %i %i %i\n", shape.z, shape.ap[0].x, shape.ap[0].y,
shape.ap[1].x, shape.ap[1].y );
printf( "%i\n", sizeof( shape ) );
return shape;
}

What is your next step?
=?GB2312?B?0rvK18qr?=
Guest
 
Posts: n/a
#3: Nov 21 '08

re: A little comments of ctypes and construct.


I didn't try your code. That might be working since it a completely
different method.

What mean is

pack works:
=========================
class POINT(Structure):

_fields_ = [('x', c_int), ('y', c_int)]

p = POINT(1,2) p.x, p.y (1, 2) str(buffer(p))
s = str(buffer(p))
=========================

unpack doesn't
=========================
p2 = POINT() ctypes.memmove(p2, s, ctypes.sizeof(POINT)) 14688904
p2.x, p2.y
=========================

I am not trying to parse data generated by a dll, but data received
from network.
That's also why I need Big Endian.

On Nov 21, 6:30 pm, Aaron Brady <castiro...@gmail.comwrote:
Quote:
On Nov 21, 2:28 am, 一首诗 <newpt...@gmail.comwrote:
>
>
>
Quote:
Hi all,
>
Quote:
Recently I asked a question on this group:
>
Quote:
Quote:
>What's your choice when handle complicated C structures.
snip
>
Quote:
typedef struct _Point
{
int x;
int y;
>
Quote:
} Point;
>
Quote:
typedef struct _Shape
{
int z;
Point ap[2];
>
Quote:
}Shape;
snip
Quote:
2. BigEndianStructure can not be nested. So. If you need bid endian,
you got bad luck.
>
A bug is filed about this.
>
I have this code working:
>
import ctypes as c
class Point( c.LittleEndianStructure ):
_fields_= [
( 'x', c.c_int ),
( 'y', c.c_int )
]
>
class Shape( c.LittleEndianStructure ):
_fields_= [
( 'z', c.c_int ),
( 'ap', Point* 2 )
]
>
lib= c.WinDLL( 'ng36ext.pyd' )
lib.make.argtypes= [ ]
lib.make.restype= Shape
shape= lib.make( )
print shape.z, shape.ap[0].x, shape.ap[0].y, shape.ap[1].x, shape.ap
[1].y
>
/Output:
>
10 20 30 40 50
20
10 20 30 40 50
>
/Definition for 'make':
>
Shape make( void ) {
Shape shape;
shape.z= 10;
shape.ap[ 0 ].x= 20;
shape.ap[ 0 ].y= 30;
shape.ap[ 1 ].x= 40;
shape.ap[ 1 ].y= 50;
printf( "%i %i %i %i %i\n", shape.z, shape.ap[0].x, shape.ap[0].y,
shape.ap[1].x, shape.ap[1].y );
printf( "%i\n", sizeof( shape ) );
return shape;
>
}
>
What is your next step?
Mark Tolonen
Guest
 
Posts: n/a
#4: Nov 21 '08

re: A little comments of ctypes and construct.



"一首诗" <newptcai@gmail.comwrote in message
news:7d2c0a73-4ce1-46e1-b2f5-f5301e5be95b@35g2000pry.googlegroups.com...
Quote:
I didn't try your code. That might be working since it a completely
different method.
>
What mean is
>
pack works:
=========================
class POINT(Structure):
>
_fields_ = [('x', c_int), ('y', c_int)]
>
p = POINT(1,2) p.x, p.y (1, 2) str(buffer(p))
s = str(buffer(p))
=========================
>
unpack doesn't
=========================
p2 = POINT() ctypes.memmove(p2, s, ctypes.sizeof(POINT)) 14688904
p2.x, p2.y
=========================
>
I am not trying to parse data generated by a dll, but data received
from network.
That's also why I need Big Endian.
struct.unpack can do what you want as well:
Quote:
Quote:
Quote:
>>import struct
>>data='\x01\x02\x03\x04\x11\x12\x13\x14\x21\x22\x 23\x24\x31\x32\x33\x34\x41\x42\x43\x44'
>>[hex(a) for a in struct.unpack('>LLLLL',data)]
['0x1020304', '0x11121314', '0x21222324', '0x31323334', '0x41424344']

-Mark

Closed Thread