简体   繁体   English

Python无法使用Python的ctypes读取包含char数组的结构

[英]Python Failed to read a structure containing a char array using Python's ctypes

I wrote a tiny dll in C ,this is my .c file . 我用C写了一个小dll,这是我的.c文件。

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. 我试图使用python调用导出的c函数。这是我的.py文件。

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 c struct ,I always got random values . 当我尝试在返回的c结构中读取数组时,我总是得到随机值。

But if I use int arrays instead of char arrays in the .cpp and the .py files ,I can get right values as expected . 但是如果我在.cpp和.py文件中使用int数组而不是char数组,我可以按预期获得正确的值。 Why? 为什么?

Error when using ctypes module to acess a DLL written in C Related question here,I guess I should not return structs by value here ,because how structs are returned is implementation defined. 使用ctypes模块访问用C编写的DLL时出错相关问题在这里,我想我不应该在这里按值返回结构,因为返回的结构是实现定义的。

I was able to get the correct values by declaring the return type as POINTER(MyStruct) , so it seems Python treats returning a structure as returning a pointer to that structure. 通过将返回类型声明为POINTER(MyStruct) ,我能够获得正确的值,因此似乎Python将返回结构视为返回指向该结构的指针。 A more natural way of returning a structure would be to return it as an output parameter. 返回结构的更自然的方法是将其作为输出参数返回。 I give examples of both below. 我举两个例子。

As you stated, using func.restype = MyStruct worked correctly for c_int * 3 as the structure member, but I found only func.restype = POINTER(MyStruct) worked for both c_char * 3 and c_int * 3 members when the struct is used as a return value. 如你所述,使用func.restype = MyStruct正确地为c_int * 3作为结构成员,但我发现当结构被用作时,只有func.restype = POINTER(MyStruct)适用于c_char * 3c_int * 3成员返回值。

test.c 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 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 

You will face a problem with Interfacing c/c++ DLL's with python if you wouldn't use Visual Studio. 如果你不使用Visual Studio,你将面临使用python连接c / c ++ DLL的问题。 At times you might get off with petty walkabout, of your codes The problem faced with MinGW [ I have not used Clang ] is that the DLL is formed but the Encoding of it is Different from that expected . 有时候你的代码很小便可能会出现问题.MinGW [我没有使用过Clang]面临的问题是DLL已经形成但是它的编码与预期的不同。

https://msdn.microsoft.com/en-us/library/windows/desktop/ms680339(v=vs.85).aspx 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 这是Windows可移植可执行(PE)标头结构的链接

Only Visual Studio [as of now] is able to generate Windows Executable Shared Libraries . 只有Visual Studio [截至目前]才能生成Windows可执行文件共享库

The problem won't persist if Linux systems are used. 如果使用Linux系统,问题将不会持续存在。 I don't know about Macintosh. 我不知道Macintosh。

As much the Code is concerned you need to add the Pointer to the Structure MyStruct which you would be using for calculation on the Dll side [ this is avoiding the problem with a workabout]. 对于Code而言,您需要将指针添加到结构MyStruct中,您将在Dll端使用它进行计算[这可以避免工作区的问题]。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM