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

3

我有一个Delhi DLL,其中暴露了一个具有以下签名的函数:

Function MyFunc(ObjID : Cardinal) : TMyRec; stdcall;

记录的定义如下:

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

type TMyItemRec = record
  ID : Cardinal;
  Params : array of String;
end;

现在我的问题是:我如何使用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))]

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

my_dll = windll.Script

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

    return my_dll.Script_GetClilocRec(ID)

我遇到了访问冲突错误。
1个回答

5
你不能将Delphi管理类型(如动态数组)传递给非Delphi代码,也不能指望使用这些数据类型调用函数。
你需要重新设计接口,使用简单类型和包含简单类型的记录。如果需要使用数组,则需要传递指向第一个元素和长度的指针,而不是使用Delphi特定的管理类型。采用Windows API作为设计交互接口的模板。
另外,你需要处理的另一件事是,在Delphi中,函数返回值与大多数其他Windows编译器处理方式不同。因此,那些不适合在寄存器中的记录需要作为var参数传递,而不是作为函数返回值。

谢谢您的回复。您最后一段话是什么意思?我可以看一下小的代码示例吗? - Lorenzo Persichetti
我的意思是,如果记录的大小大于寄存器的大小,Delphi和其他工具处理函数返回值的方式是不同的。因此,不要将记录作为返回值传递。 - David Heffernan
他很可能也会使用类似OLE的数据类型和可变数组。 - Arioch 'The

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接