【发布时间】:2021-08-24 14:50:35
【问题描述】:
我有一些用 Delphi 编写的函数,我需要通过 DLL 从其他编程语言(例如 Python)访问这些函数。 Delphi 函数采用某种数字(整数或双精度数)、数组或矩阵(数组的数组)作为输入和返回类型。
在 Delphi 中,通过一个简单的测试函数可以很好地传递整数:
library Delphi_Library;
uses
System.SysUtils;
function AddIntegers(const _a, _b: integer): integer; stdcall;
begin
Result := _a + _b;
end;
exports
AddIntegers;
begin
end.
并从 Python 调用它:
import ctypes
Dll = ctypes.WinDLL('Delphi_Library')
a = ctypes.c_int(5)
b = ctypes.c_int(7)
c = Dll.AddIntegers(a, b)
print(c)
但是,我不能直接将数组传递给 DLL,但据我所知,我需要使用指向数组的指针。另外我不能使用数组作为返回类型,所以我想改变一个输入数组。作为测试函数,我想编写一个小函数,它将指向数组array_in 的指针和它的长度size_array_in 作为输入,并将另一个数组array_out 和它的大小size_array_out 设置为相同的值。它还将数组的最后一个元素作为双精度返回。
我在 Delphi 中的代码如下所示:
library Delphi_Library;
uses
System.SysUtils;
type
TArray = Array of Double;
PArray = ^TArray;
function ReturnArray(array_in: pointer; size_array_in: integer; array_out: pointer; size_array_out: integer): Double; stdcall;
var
i: Integer;
P_value: PDouble;
arr: TArray;
begin
Result := 0;
P_value := PDouble(array_in);
setlength(arr, size_array_out);
//arr := P_in^;
for i := 0 to size_array_in-1 do
begin
arr[i] := P_value^;
inc(P_value);
end;
array_out := @arr;
size_array_out := Length(arr);
end;
exports
ReturnArray;
begin
end.
在 Python 中
ReturnArray = Dll.ReturnArray
ReturnArray.restype = ctypes.c_double
ReturnArray.argtypes = ctypes.POINTER(ctypes.c_double*8), ctypes.c_int, ctypes.POINTER(ctypes.c_double*8), ctypes.c_int
data_in = (ctypes.c_double*8)(*range(32, 40))
data_out = (ctypes.c_double*8)(*range(8))
num_1 = 8
num_2 = 8
print('input', list(data_in), list(data_out))
retval = ReturnArray(data_in, num_1, data_out, num_2)
print('output', retval, list(data_in), list(data_out))
但是,在调用 Delphi-DLL 函数后,我仍然得到 data_out 的相同数组/列表。
那么如何将数组或指向数组的指针从另一种编程语言解析为 Delphi 数组?我的最终目标是编写一个接口,以便能够从任何支持调用 C-DLL 的编程语言中使用具有像 function AnyFunction(a: Array of Double; b: Array of Array of Double): Array of Double 这样定义的 Delphi 函数。
【问题讨论】:
-
我不知道
Python端应该是什么样子,但我知道你不能在 Delphi 端为array_out分配任何东西,并希望它反映在调用范围。您可以(可能)更改传入数组中的元素,但不能更改整个数组,就像您在此处使用array_out := @arr;所做的那样。这不起作用的第一个原因是array_out是一个输入参数(缺少out或var),但即使修复它迟早会导致其他问题,因为setlength使用Delphi 的本地堆子分配器,Python未知。