如何使用ctypes访问返回在Delphi dll中编码的自定义类型的函数?

Lor*_*tti 3 python delphi ctypes types

我有一个德里DLL暴露了一个具有以下签名的函数:

Function MyFunc(ObjID : Cardinal) : TMyRec; stdcall;
Run Code Online (Sandbox Code Playgroud)

记录的定义如下:

type TMyRec = record
  Count : Cardinal;
  Items : array of TMyItemRec;
end;

type TMyItemRec = record
  ID : Cardinal;
  Params : array of String;
end;
Run Code Online (Sandbox Code Playgroud)

现在我的问题是:如何使用Python ctypes访问调用dll的MyFunc的结果?我编写了两个模仿类型的类

from ctypes import *
class TMyItemRec(Structure):
    _fields_ = [("ID", c_int), ("Params", POINTER(c_wchar_p))]

class TMyRec(Structure):
    _fields_ = [("Count", c_int), ("Params", POINTER(TMyItemRec))]
Run Code Online (Sandbox Code Playgroud)

但是当我尝试读取这样的数据时:

my_dll = windll.Script

def GetMyRec(ID):
    my_dll.MyFunc.argtypes = [c_uint]
    my_dll.MyFunc.restype = TClilocRec

    return my_dll.Script_GetClilocRec(ID)
Run Code Online (Sandbox Code Playgroud)

我收到访问冲突错误.

Dav*_*nan 5

您无法将Delphi托管类型(如动态数组)传递给非Delphi代码.您不能期望使用这些数据类型调用函数.

您需要重新设计界面.您需要使用包含简单类型的简单类型和记录.如果你需要数组,那么你必须传递指向第一个元素和长度的指针,而不是使用特定于Delphi的托管类型.使用Windows API作为模板来设计互操作接口.

您需要处理的另一件事是Delphi中的函数返回值的处理方式与大多数其他Windows编译器不同.因此,不适合寄存器的记录需要作为var参数而不是函数返回值传递.