You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi编写DLL的数组参数传递及跨语言(如Python)调用问题

问题根源分析
  • 错误1:Delphi端array_out和size_array_out都是按值传递的形参,修改形参只会改动栈上的副本,不会对外部传入的实际参数生效
  • 错误2:你使用了Delphi特有的托管动态数组TArray = Array of Double作为中间存储,这类数组的内存由Delphi runtime自动管理,函数执行结束后就会被释放,即使把地址赋值给array_out,返回给Python的也是野指针,完全无法使用
  • 错误3:你没有直接操作Python端预先分配的data_out内存,而是把值写到了Delphi自己分配的动态数组里,外部自然读取不到修改结果
修正方案

1. Delphi端代码修正

核心逻辑是直接操作传入的指针指向的内存,不要用Delphi特有托管类型做跨语言传递:

library Delphi_Library;

uses
  System.SysUtils;

function AddIntegers(const _a, _b: integer): integer; stdcall;
begin
    Result := _a + _b;
end;

function ReturnArray(array_in: PDouble; size_array_in: Integer; 
  array_out: PDouble; var size_array_out: Integer): Double; stdcall;
var
  i: Integer;
  copy_count: Integer;
begin
  Result := 0;
  // 先判断输出缓冲区长度是否足够
  if size_array_out < size_array_in then
  begin
    // 不足时返回需要的长度,外部重新分配内存后再调用
    size_array_out := size_array_in;
    Exit;
  end;
  // 计算实际复制的元素数
  copy_count := size_array_in;
  size_array_out := copy_count;
  // 直接往传入的输出缓冲区写数据
  for i := 0 to copy_count - 1 do
  begin
    array_out^ := array_in^;
    Result := array_in^; // 最后一个元素就是返回值
    Inc(array_in);
    Inc(array_out);
  end;
end;

exports
  AddIntegers,
  ReturnArray;

begin
end.

注意:如果需要兼容纯C调用约定,把var size_array_out: Integer改成size_array_out: PInteger,代码里操作size_array_out^即可,和var参数本质是一样的。

2. Python端代码修正

不需要给数组套POINTER,ctypes的数组本身传递时就会自动转成首元素指针,需要修改的长度参数要传引用:

import ctypes
Dll = ctypes.WinDLL('Delphi_Library')

# 先测试整数加法
a = ctypes.c_int(5)
b = ctypes.c_int(7)
c = Dll.AddIntegers(a, b)
print("加法结果:", c)

# 配置数组函数
ReturnArray = Dll.ReturnArray
ReturnArray.restype = ctypes.c_double
ReturnArray.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.c_int, 
                        ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_int)]

# 准备输入输出数组
data_in = (ctypes.c_double * 8)(*range(32, 40))
data_out = (ctypes.c_double * 8)() # 先分配8个元素的缓冲区
num_in = ctypes.c_int(8)
num_out = ctypes.c_int(8)

print('调用前输入:', list(data_in))
print('调用前输出:', list(data_out))

retval = ReturnArray(data_in, num_in, data_out, ctypes.byref(num_out))

print('返回值:', retval)
print('实际输出长度:', num_out.value)
print('调用后输出:', list(data_out))
扩展到二维数组/矩阵的方案

跨语言传递二维数组统一约定为行优先的连续内存块,传递参数约定为:

  • 矩阵首元素指针 PDouble
  • 行数 Integer
  • 列数 Integer

比如接收二维数组的Delphi函数可以这么写:

function ProcessMatrix(matrix: PDouble; rows: Integer; cols: Integer): Double; stdcall;
var
  i, j: Integer;
  current_val: Double;
begin
  for i := 0 to rows - 1 do
    for j := 0 to cols - 1 do
    begin
      current_val := matrix^;
      // 这里写你的矩阵处理逻辑
      Inc(matrix);
    end;
  // 返回计算结果
end;

Python端传递二维数组的时候,先把二维列表拉平成一维连续数组再传递即可。

内容的提问来源于stack exchange,提问作者pjuergens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 02:51:03