Python calling C Common library with custom ctypes structures

I am invoking the C library C from Python on a Linux system.

The problem I'm facing is that the function inside the C library takes a pointer to a structure as an argument. Then it fills the memory for the array of structures, fills the array with data and returns them. So I defined the function as

from ctypes import * class myStruct(Structure): _fields_ = [("id", c_uint), "name", c_char*256)] library.func.argtypes = [POINTER(myStruct)] 

Then I call it this:

 Myfoo = myStruct Foo = pointer(Myfoo) Bar = library.func(Foo) for i in range(Bar): print("id = %u, name = %s" % (Foo[i].id, Foo[i].name)) 

The bar contains the number of structures that have been assigned func.

No matter what I do, I cannot get data from Foo. I tried several different variations of this for several months. I can look at the logs from the C library, and I know that I get the data and return it, but I cannot find a way to extract it from Python.

Any thoughts?

+6
source share
2 answers

Ok, then you only need a few small updates.

First, declaring your argument is disabled, but that probably doesn't matter. A pointer is a pointer as regards the python-c value translation mechanism. The most accurate would be POINTER(POINTER(myStruct)) , but to simplify the task, just use:

 library.func.argtypes = [c_void_p] 

Next, you don’t have to worry about instantiating myStruct to indicate your argument; you only need the correct pointer and a pointer to it. func will highlight the actual instances of myStruct . So start with:

 Foo = ctypes.POINTER(myStruct)() 

Now we can call it. We have myStruct* , but we will give it a pointer so func can change it. We do not need to create a whole other pointer object, so we will use a lighter byref :

 Bar = library.func(byref(Foo)) 

Now you can iterate through Foo[i] .

 for i in range(Bar): print("id = %u, name = %s" % (Foo[i].id, Foo[i].name)) 
+4
source

If I got a func prototype right from your comment in the question, then this should do:

C code

 #include <stdlib.h> #include <stdio.h> struct Foo { unsigned int id; char name[256]; }; __declspec(dllexport) int func(struct Foo **ppFoo) { int i; struct Foo *foo = malloc(5 * sizeof(struct Foo)); for(i=0;i<5;i++) { foo[i].id = i; sprintf_s(foo[i].name,_countof(foo[i].name),"Name#%d",i); } *ppFoo = foo; return 5; } 

Python code

 from ctypes import * dll = CDLL('x') class Foo(Structure): _fields_ = [ ('id',c_uint), ('name',c_char*256)] pfoo = POINTER(Foo)() count = dll.func(byref(pfoo)) for i in xrange(count): print pfoo[i].id,pfoo[i].name 

Exit

 0 Name#0 1 Name#1 2 Name#2 3 Name#3 4 Name#4 

Note that you still need free allocated memory ...

+5
source

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


All Articles