【问题标题】:Passing binary data to a dll function in D7将二进制数据传递给 D7 中的 dll 函数
【发布时间】:2012-02-15 15:21:59
【问题描述】:

谁能给我提供传递任意字节数的工作示例 通过参数传递给一个dll函数?

我想在没有任何额外内存单元的情况下这样做,只对基本的窗口类型进行操作。

每次调用我需要“发送”大约 300 kb 的数据。

在客户端分配的内存在客户端也应该是空闲的吗?

【问题讨论】:

  • 我们会,但我们想看看你已经尝试过什么......
  • 关于分配和解除分配:要么在调用方同时执行,要么在被调用方同时执行。因此,如果您想在客户端分配它,也可以在客户端释放它。

标签: delphi dll delphi-7


【解决方案1】:

DLL 函数应如下所示:

procedure Test(Buffer: Pointer; Length: Integer); stdcall;
begin
  //Buffer points to the start of the buffer. 
  //The Buffer size if Length bytes.
end;

假设您从另一个 Delphi 模块调用它,调用可能如下所示:

procedure Test(Buffer: Pointer; Length: Integer); stdcall; external 'test.dll';

procedure CallTest;
var
  Buffer: array of Byte;
begin
  SetLength(Buffer, 1000);
  //populate Buffer
  Test(@Buffer[0], Length(Buffer));
end;

最好定义一个需要在同一个模块中分配和释放内存的接口。

上面的例子在调用者的模块中分配和释放。这意味着Test 方法要么必须在返回之前完全处理Buffer,要么在返回之前复制Buffer 的内容。

现在,虽然可以在被调用者的模块中进行分配和解除分配,但这并不常见。它不太常见,因为这样做通常不太方便。它通常需要更多的 API 功能,或者更复杂的接口。当调用者无法确定缓冲区的适当大小时,您将被推入被调用者分配的路线。

当数据从调用者传递到被调用者时,调用者分配总是最好的选择。当数据流向另一个方向时,被调用方分配的可能性更大。

【讨论】:

  • 你没有说任何关于释放的事情:因为Buffer 是一个动态数组,当CallTest 离开时它会被释放。因此,如果 DLL 打算在 Test 调用之后保留数据,则必须制作自己的副本。
  • 我认为当你从模块函数返回一个缓冲区然后在调用函数中释放它时应该完成模块分配(例如模块中的LocalAlloc和@987654330 @ 在调用者中)。
  • @kobik 一般来说,如果可能的话,人们会努力避免被调用者分配。但是,是的,有时它是正确的解决方案。
  • OP 要求传递“任意字节”,因此我将函数声明为采用 Pointer 参数而不是 PByte 参数。该函数可以在需要时在内部将Pointer 强制转换为PByte,但这种方式允许调用者传递任何类型的内存地址,而无需在其末尾手动强制转换。
  • @kobik:如果 DLL 必须将内存返回给调用者,最好从 DLL 中导出一个额外的函数,允许 DLL 释放内存,因为只有它知道内存是如何释放的首先分配,因此如何正确释放它。最好的选择是让调用者分配内存并将其传递给 DLL 以根据需要填写内容。这两种模型各有利弊。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-28
  • 2021-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多