[Tutor] Get the structure values from a c file

eryksun eryksun at gmail.com
Mon Dec 17 13:56:30 CET 2012


On Sun, Dec 16, 2012 at 10:12 PM, Marefe Serentas <marszydril at gmail.com> wrote:
>
> I want to create a python script that will store the value of the structure
> MainStruct from the c file.


Try pycparser to parse C source code. To load a library and call its
functions you can use ctypes.

http://docs.python.org/2/library/ctypes
http://docs.python.org/3/library/ctypes
http://code.google.com/p/pycparser

Below I adapted your example for ctypes.


> #define max (3)
>
> typedef struct A
> {
>     int a;
>     char b;
> }A;
>
> typedef struct MainStruct
> {
>     A var1;
>     int var2;
>     int var3[max];
> }Main;


    import ctypes

    max = 3

    class A(ctypes.Structure):
        _fields_ = [
          ('a', ctypes.c_int),
          ('b', ctypes.c_char),
        ]

    class Main(ctypes.Structure):
        _fields_ = [
          ('var1', A),
          ('var2', ctypes.c_int),
          ('var3', ctypes.c_int * max),
        ]


Per your typedef, the 2nd structure is named "Main".
c_int * max creates an array.


> void generate()
> {
>     MainStruct myMain = {0};
>     myMain.var1.a = 1
>     myMain.var1.b = 'a'
>     myMain.var2 = 3
>     myMain.var3[0] = -3
>     myMain.var3[1] = 6
>     myMain.var3[2] = 18
> }


That would have to be "struct MainStruct myMain". Also, you're missing
semicolons on all but the first line.

It's simpler to let the caller manage memory. Here's the function
written to take a pointer:


    void generate(Main *myMain)
    {
        myMain->var1.a = 1;
        myMain->var1.b = 'a';
        myMain->var2 = 3;
        myMain->var3[0] = -3;
        myMain->var3[1] = 6;
        myMain->var3[2] = 18;
    }


To call this, first load the library (e.g. "lib.so") and define the
prototype in Python. Setting "argtypes" is helpful because ctypes type
checks arguments. A TypeError is better than a segfault.


    lib = ctypes.cdll.LoadLibrary('./lib.so')
    generate = lib.generate
    generate.argtypes = [ctypes.POINTER(Main)]
    generate.restype = None


    >>> myMain = Main()
    >>> generate(myMain)
    >>> myMain.var1.a, myMain.var1.b, myMain.var2
    (1, 'a', 3)
    >>> list(myMain.var3)
    [-3, 6, 18]

It passes a pointer to myMain based on the argtypes prototype, but you
can also explicitly use generate(ctypes.byref(myMain)).


More information about the Tutor mailing list