如何调用 delphi 函数,该函数采用 returns 自定义类型的指针,来自 Python?
How do I call a delphi function that takes and returns pointers of custom type from Python?
此题与How to access with ctypes to functions returning custom types coded in a Delphi dll?相似。我认为这个不同的地方是我正在查看的 delphi 函数签名将指针作为参数而不是 delphi 类型。
它也类似于 Python pass Pointer to Delphi function 除了评论中提到的,该问题缺少必要的信息。
如何调用 delphi 函数,该函数采用 Python 自定义类型的 returns 指针?
我通过在 Python.
中加载带有 ctypes 的 DLL 来调用 delphi 函数
>>> from ctypes import *
>>> path = "C:\test.dll"
>>> lib = windll.LoadLibrary(path)
>>> lib.myFunc
<_FuncPtr object at 0x21324905>
delphi 函数 "myFunc" 的签名如下:
Procedure myFunc(Ptr:Pointer;Var Result:Pointer);Export;
两个指针都应该是自定义数据类型,例如
Type
PSingleArray = ^SingleArray;
SingleArray = Record
LowIndex : SmallInt;
HighIndex : SmallInt;
Data : Array [0..1000] of Single;
end;
通过 ctypes tutorial and the docs 看来解决这个问题的方法是使用 "Structure" 在 Python 中创建相似的类型。我认为我做得很好;但是,当我去调用 myFunc 时,出现了访问冲突错误。
>>> class SingleArray(Structure):
>>> _fields_ = [("HighIndex", c_int), ("LowIndex", c_int), ("Data", c_int * 10)]
>>> ...
>>> lib.myFunc.argtypes = [POINTER(SingleArray)]
>>> lib.myFunc.restype = POINTER(SingleArray)
>>> # initialize the input values
>>> input = SingleArray()
>>> a = c_int * 10
>>> data = a(1,2,3,4,5,6,7,8,9,10)
>>> input.Data = data
>>> input.HighIndex = 2
>>> input.LowIndex = 1
>>> # Here comes the access violation error
>>> ret = lib.myFunc(input)
WindowsError: exception: access violation reading 0x00000002
我是 ctypes 和 delphi 的新手,所以我可能遗漏了一些明显的东西。
我可以看到以下简单问题:
- Delphi
Smallint
是有符号的 16 位类型。最多匹配 c_short
.
- Delphi
Single
是 IEEE-754 浮点值。最多匹配 c_float
.
- Delphi 类型的数组长度为 1001。你的数组长度为 10。
- Delphi 函数有两个参数,没有 return 值。您的
argtypes
和 restype
作业不匹配。
- 您的 ctypes 代码使用 stdcall 调用约定,但 Delphi 函数似乎使用 Delphi 特定的
register
调用约定。这使得该函数无法从除另一个 Delphi 模块以外的任何地方调用。
- 谁拥有通过
Result
参数编辑的内存 return 并不明显,也不清楚如何释放它。
更重要的是,结构中的数组似乎是可变长度的。使用 ctypes 编组将非常棘手。你当然不能使用 Structure._fields_
.
如果您可以更改 Delphi DLL,请这样做。在目前的形式下,它基本上无法从 ctypes 中使用。即使来自 Delphi 代码,使用起来也令人震惊。
如果您不能更改 Delphi DLL,那么我认为您需要在 Delphi 或 FPC 中编写一个适配器 DLL,它为您的 Python 要使用的代码。
此题与How to access with ctypes to functions returning custom types coded in a Delphi dll?相似。我认为这个不同的地方是我正在查看的 delphi 函数签名将指针作为参数而不是 delphi 类型。
它也类似于 Python pass Pointer to Delphi function 除了评论中提到的,该问题缺少必要的信息。
如何调用 delphi 函数,该函数采用 Python 自定义类型的 returns 指针?
我通过在 Python.
中加载带有 ctypes 的 DLL 来调用 delphi 函数>>> from ctypes import *
>>> path = "C:\test.dll"
>>> lib = windll.LoadLibrary(path)
>>> lib.myFunc
<_FuncPtr object at 0x21324905>
delphi 函数 "myFunc" 的签名如下:
Procedure myFunc(Ptr:Pointer;Var Result:Pointer);Export;
两个指针都应该是自定义数据类型,例如
Type
PSingleArray = ^SingleArray;
SingleArray = Record
LowIndex : SmallInt;
HighIndex : SmallInt;
Data : Array [0..1000] of Single;
end;
通过 ctypes tutorial and the docs 看来解决这个问题的方法是使用 "Structure" 在 Python 中创建相似的类型。我认为我做得很好;但是,当我去调用 myFunc 时,出现了访问冲突错误。
>>> class SingleArray(Structure):
>>> _fields_ = [("HighIndex", c_int), ("LowIndex", c_int), ("Data", c_int * 10)]
>>> ...
>>> lib.myFunc.argtypes = [POINTER(SingleArray)]
>>> lib.myFunc.restype = POINTER(SingleArray)
>>> # initialize the input values
>>> input = SingleArray()
>>> a = c_int * 10
>>> data = a(1,2,3,4,5,6,7,8,9,10)
>>> input.Data = data
>>> input.HighIndex = 2
>>> input.LowIndex = 1
>>> # Here comes the access violation error
>>> ret = lib.myFunc(input)
WindowsError: exception: access violation reading 0x00000002
我是 ctypes 和 delphi 的新手,所以我可能遗漏了一些明显的东西。
我可以看到以下简单问题:
- Delphi
Smallint
是有符号的 16 位类型。最多匹配c_short
. - Delphi
Single
是 IEEE-754 浮点值。最多匹配c_float
. - Delphi 类型的数组长度为 1001。你的数组长度为 10。
- Delphi 函数有两个参数,没有 return 值。您的
argtypes
和restype
作业不匹配。 - 您的 ctypes 代码使用 stdcall 调用约定,但 Delphi 函数似乎使用 Delphi 特定的
register
调用约定。这使得该函数无法从除另一个 Delphi 模块以外的任何地方调用。 - 谁拥有通过
Result
参数编辑的内存 return 并不明显,也不清楚如何释放它。
更重要的是,结构中的数组似乎是可变长度的。使用 ctypes 编组将非常棘手。你当然不能使用 Structure._fields_
.
如果您可以更改 Delphi DLL,请这样做。在目前的形式下,它基本上无法从 ctypes 中使用。即使来自 Delphi 代码,使用起来也令人震惊。
如果您不能更改 Delphi DLL,那么我认为您需要在 Delphi 或 FPC 中编写一个适配器 DLL,它为您的 Python 要使用的代码。