Python Could not read structure containing char array using Python types
I wrote a tiny dll in C, this is my .c file.
struct my_struct
{
char arr[3];
};
__declspec(dllexport) struct my_struct func()
{
struct my_struct m;
m.arr[0] = 1;
m.arr[1] = 2;
m.arr[2] = 3;
return m;
};
//compiled to testdll.dll
I tried to call the exported c function using python. This is my .py file.
from ctypes import *
class MyStruct(Structure):
_fields_ = [("arr", c_char * 3)]
f = cdll.testdll.func
f.restype = MyStruct
for i in f().arr:
print(i)
When I tried to read the array in the returned structure c, I always got random values.
But if I use int arrays instead of char arrays in .cpp and .py files, I can get the correct values as expected. Why?
Error when using ctypes module to access DLL, written in the C . See this question here, I think I shouldn't be returning structs by value here because since the returned structs are implementation defined.
source to share
I was able to get the correct values by declaring the return type as POINTER(MyStruct)
, so it seems like Python treats the return of a structure as returning a pointer to that structure. A more natural way to return the structure would be to return it as an out parameter. I've provided examples of both below.
As you said, usage func.restype = MyStruct
worked correctly for c_int * 3
both a member of a struct, but I found that it only func.restype = POINTER(MyStruct)
worked for both members c_char * 3
and c_int * 3
when a struct is used as a return value.
test.c
struct my_struct
{
char arr[3];
};
__declspec(dllexport) struct my_struct func()
{
struct my_struct m = {1,2,3};
return m;
};
__declspec(dllexport) void func2(struct my_struct* m)
{
m->arr[0] = 4;
m->arr[1] = 5;
m->arr[2] = 6;
};
test.py
from ctypes import *
class MyStruct(Structure):
_fields_ = ('arr',c_char * 3),
dll = CDLL('test')
func = dll.func
func.argtypes = None
func.restype = POINTER(MyStruct)
func2 = dll.func2
func2.argtypes = POINTER(MyStruct),
func2.restype = None
x = func()
print(x.contents.arr[0],x.contents.arr[1],x.contents.arr[2])
m = MyStruct()
func2(m)
print(m.arr[0],m.arr[1],m.arr[2])
Output
1 2 3
4 5 6
source to share
You will have a problem with Interfacing c / C ++ DLL with python if you don't use Visual Studio. From time to time, you can get off the shallow walk on your codes. The problem MinGW [I haven't used Clang] is facing is that the DLL has been generated, but its encoding is different from what is expected.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms680339(v=vs.85).aspx
Here is the link of the Windows Portable Executable (PE) header structure
Only Visual Studio [at the moment] can generate Windows Shared Library executables .
The problem will not persist when using Linux systems. I don't know about Macintosh.
As in the code, you need to add a pointer to the MyStruct structure that you will use to calculate on the Dll side [this avoids the problem with the workabout].
source to share