Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access C-Declared Nested Struct from Python

I have statically declared a large structure in C, but I need to use this same data to do some analysis in Python. I'd rather not re-copy this data in to Python to avoid errors, is there a way to access (read only) this data directly in Python? I have looked at "ctypes" and SWIG, and neither one of them seems to provide what I'm looking for....

For example I have:

/* .h file */

typedef struct
{
  double data[10];
} NestedStruct;


typedef struct
{
   NestedStruct array[10];
} MyStruct;

/* .c file */

MyStruct the_data_i_want = 
{
  {0},
  {
   {1,2,3,4}
  },
  {0},
};

Ideally, I'd like something that would allow me to get this into python and access it via the_data_i_want.array[1].data[2] or something similar. Any thoughts? I got swig to "work" in the sense that I was able to compile/import a .so created from my .c file, but I couldn't access any of it through cvars. Maybe there's another way? It seems like this should't be that hard....


Actually, I figured it out. I'm adding this because my reputation does not allow me to answer my own question within 8 hours, and since I don't want to have to remember in 8 hours I will add it now. I'm sure there's a good reason for this that I don't understand.

Figured it out.

1st I compiled my .c file into an library:

Then, I used types to define a python class that would hold the data:

from ctypes import *

class NestedStruct(Structure):
    _fields_ = [("data", c_double*10)]

class MyStruct(Structure):
    _fields_ = [("array", NestedStruct*10)]

Then, I loaded the shared library into python:

my_lib = cdll.LoadLibrary("my_lib.so")

Then, I used the "in_dll" method to get the data:

the_data_i_want = MyStruct.in_dll(my_lib, "the_data_i_want")

Then, I could access it as if it were C. the_data_i_want.array[1].data[2]

Note I may have messed up the syntax slightly here because my actual data structure is nested 3 levels and I wanted to simplify for illustration purposes here.

like image 632
donovandak Avatar asked Mar 08 '12 21:03

donovandak


1 Answers

You could've also in C read the data and written to a JSON-File, which you could then easily parse (usually there's a library which will even do that for you; python import json) and access form any different platform with almost every language setup you could think of. And at the same time you could've accessed you're data very similar compared to how you accessed it within you're original C code.

Just as a suggestion. This would make you're data also more portable and versatile I think, but you'll spend more time on writing and parsing the JSON as if you just read the stream of data directly from you're C code into python.

like image 89
hallole Avatar answered Sep 18 '22 00:09

hallole