A little comments of ctypes and construct.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?GB2312?B?0rvK18qr?=

    A little comments of ctypes and construct.

    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.



    2. BigEndianStruct ure 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

    #2
    Re: A little comments of ctypes and construct.

    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. BigEndianStruct ure 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.LittleEndianS tructure ):
    _fields_= [
    ( 'x', c.c_int ),
    ( 'y', c.c_int )
    ]

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

    lib= c.WinDLL( 'ng36ext.pyd' )
    lib.make.argtyp es= [ ]
    lib.make.restyp e= 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?

    Comment

    • =?GB2312?B?0rvK18qr?=

      #3
      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(P OINT)) 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...@gma il.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. BigEndianStruct ure 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.LittleEndianS tructure ):
      _fields_= [
      ( 'x', c.c_int ),
      ( 'y', c.c_int )
      ]
      >
      class Shape( c.LittleEndianS tructure ):
      _fields_= [
      ( 'z', c.c_int ),
      ( 'ap', Point* 2 )
      ]
      >
      lib= c.WinDLL( 'ng36ext.pyd' )
      lib.make.argtyp es= [ ]
      lib.make.restyp e= 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?

      Comment

      • Mark Tolonen

        #4
        Re: A little comments of ctypes and construct.


        "Ò»Ê×Ê«" <newptcai@gmail .comwrote in message
        news:7d2c0a73-4ce1-46e1-b2f5-f5301e5be95b@35 g2000pry.google groups.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(P OINT)) 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\x0 2\x03\x04\x11\x 12\x13\x14\x21\ x22\x23\x24\x31 \x32\x33\x34\x4 1\x42\x43\x44'
        >>[hex(a) for a in struct.unpack(' >LLLLL',data)]
        ['0x1020304', '0x11121314', '0x21222324', '0x31323334', '0x41424344']

        -Mark

        Comment

        Working...