C struct in Python

There is libx.so that exports 2 functions and a struct ,

 typedef struct Tag { int num; char *name; }Tag; Tag *create(int n, char *n) { Tag *t = malloc(sizeof(Tag)); t->num = n; t->name = n; return t; } void use(Tag *t) { printf("%d, %s\n", t->num, t->name); } 

I want to call create in Python and then save the Tag *res returned by create , later I will call use and pass the Tag *res stored before use , here it is (just for demonstration):

 >>>libx = ctypes.CDLL("./libx.so") >>>res = libx.create(c_int(1), c_char_p("a")) >>>libx.use(res) 

The above code might be wrong, just to demonstrate what I want to do.

And my problem is that, how can I save the result returned by create ? Since it returns a pointer to a custom struct , and I don't want to construct a struct Tag in Python, would the c_void_p trick?

UPDATE

From @David's answer, I still don't quite understand one thing:

the pointer ( c_char_p("a") ) is valid only for a while call create . As soon as create is returned, this pointer is no longer valid.

And I assign c_char_p("a") t->name to create , when the create call ends, is t->name dangling pointer? Since, according to the quoted words, this pointer no longer acts after create . Why is c_char_p("a") no longer valid?

+6
source share
2 answers

The C code that you represent is just not working. You should be much more precise about which side allocates and is responsible for the heap memory.

In your current example, you pass c_char_p("a") to C code. However, the ctypes pointer to this memory is valid only for the duration of the create call. As soon as create returns, this pointer is no longer valid. But you took a copy of the pointer inside create . Thus, a subsequent call to use may fail.

You will need to take a copy of the contents of this line and save it in the structure. If you do this, you can safely use libx.create.restype = c_void_p .

But if you want the allocated memory to be freed, you will need to provide the destroy function corresponding to the create function. With these changes, the C code will look like this:

 Tag *create(int n, char *s) { Tag *t = malloc(sizeof(Tag)); t->num = n; t->name = strdup(s); return t; } void destroy(Tag *t) { free(t->name); free(t); } 

Python code would look like this:

 libx = ctypes.CDLL("./libx.so") libx.create.restype = c_void_p res = libx.create(c_int(1), c_char_p("a")) libx.use(res) libx.destroy(res) 
+4
source

Python does reference counting. You will have to use Py_INCREF () and friends for objects that are returned from "external" libraries.

UPDATE: I don't know about .so loading with python, maybe the method suggested by @David Hefferman does this automatically.

UPDATE2: delete me!

0
source

Source: https://habr.com/ru/post/909276/


All Articles