如何调用delphi函数从Python获取并返回自定义类型的指针?

时间:2015-01-13 15:34:27

标签: python delphi pointers dll ctypes


此问题与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获取并返回自定义类型的指针?

我通过在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 tutorialthe 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的新手,所以我可能会遗漏一些明显的东西。

1 个答案:

答案 0 :(得分:2)

我可以看到以下简单问题:

  • Delphi Smallint是带符号的16位类型。最高匹配c_short
  • Delphi Single是IEEE-754浮点值。最高匹配c_float
  • Delphi类型的数组长度为1001.您的长度为10。
  • Delphi函数有两个参数,没有返回值。您的argtypesrestype分配不匹配。
  • 您的ctypes代码使用stdcall调用约定,但Delphi函数似乎使用Delphi特定的register调用约定。这使得除了另一个Delphi模块之外的其他任何东西都无法调用该函数。
  • 谁拥有通过Result参数返回的内存,以及如何解除分配它并不明显。

更重要的是,结构中的数组似乎可变长度。用ctypes编组是非常棘手的。你当然不能使用Structure._fields_

如果您可以更改Delphi DLL,请执行此操作。在目前的形式中,它基本上不能用于ctypes。即使是使用Delphi代码,它仍然令人震惊。

如果你不能改变Delphi DLL那么我认为你需要在Delphi或FPC中编写一个适配器DLL,它为你的Python代码提供了一个更合理的界面。