Reputation: 1628
This question is similar to How to access with ctypes to functions returning custom types coded in a Delphi dll?. Where I think this one is different is that the delphi function signature that I'm looking at takes pointers as arguments instead of delphi types.
It's also similar to Python pass Pointer to Delphi function except as mentioned in the comments, that question lacks necessary information.
How do I call a delphi function that takes and returns pointers of custom type from Python?
I'm calling delphi functions by loading a DLL with ctypes in Python.
>>> from ctypes import *
>>> path = "C:\\test.dll"
>>> lib = windll.LoadLibrary(path)
>>> lib.myFunc
<_FuncPtr object at 0x21324905>
The delphi function "myFunc" has a signature like:
Procedure myFunc(Ptr:Pointer;Var Result:Pointer);Export;
Where both pointers should be custom data types, e.g.
Type
PSingleArray = ^SingleArray;
SingleArray = Record
LowIndex : SmallInt;
HighIndex : SmallInt;
Data : Array [0..1000] of Single;
end;
Going through the ctypes tutorial and the docs it seems like the way to solve this is to use "Structure" to create similar types in Python. I think I'm doing it properly; however, when I go to call myFunc an Access Violation Error is raised.
>>> 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
I'm new to both ctypes and delphi, so I could be missing something obvious.
Upvotes: 1
Views: 990
Reputation: 612954
I can see the following simple problems:
Smallint
is a signed 16 bit type. That matches up to c_short
.Single
is an IEEE-754 floating point value. That matches up to c_float
.argtypes
and restype
assignments do not match.register
calling convention. This makes the function impossible to call from anything other than another Delphi module.Result
parameter, nor how to deallocate it.More significantly, it seems likely that the array in the structure is of variable length. That will be quite tricky to marshal with ctypes. You certainly cannot do so using Structure._fields_
.
If you can change the Delphi DLL, do so. In its current form it is essentially unusable from ctypes. Even from Delphi code it is appalling to use.
If you cannot change the Delphi DLL then I think you'll need to write an adapter DLL, in Delphi or FPC, that presents a more sane interface for your Python code to work with.
Upvotes: 2