By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
444,001 Members | 1,176 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 444,001 IT Pros & Developers. It's quick & easy.

A little comments of ctypes and construct.

P: n/a
Hi all,

Recently I asked a question on this group:

>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.
Nov 21 '08 #1
Share this Question
Share on Google+
3 Replies


P: n/a
On Nov 21, 2:28 am, 一首诗 <newpt...@gmail.comwrote:
Hi all,

Recently I asked a question on this group:
What's your choice when handle complicated C structures.
snip
>
typedef struct _Point
{
int x;
int y;

} Point;

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

}Shape;
snip
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?
Nov 21 '08 #2

P: n/a
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:
On Nov 21, 2:28 am, 一首诗 <newpt...@gmail.comwrote:
Hi all,
Recently I asked a question on this group:
>What's your choice when handle complicated C structures.
snip
typedef struct _Point
{
int x;
int y;
} Point;
typedef struct _Shape
{
int z;
Point ap[2];
}Shape;
snip
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?
Nov 21 '08 #3

P: n/a

"一首诗" <ne******@gmail.comwrote in message
news:7d**********************************@35g2000p ry.googlegroups.com...
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:
>>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

Nov 21 '08 #4

This discussion thread is closed

Replies have been disabled for this discussion.