如何将内存流从我的应用程序传递到 DLL 或从 DLL 检索内存流?

2024-03-13

假设我有一个TMemoryStream我需要传递到我的 DLL 并返回TMemoryStream(位图流)来自 DLL。

我想我的 DLL 会有:

procedure Process(
  InBuff: Pointer; 
  InBuffSize: Integer; 
  var OutBuff: Pointer; 
  var OutBuffSize: Integer
); stdcall;

The InBuff很容易(我认为)。我通过TMemoryStream.Memory and TMemoryStream.Size.

问题是我该如何分配OutBuff在 DLL 中,调用者应用程序可以将其转换回TMemoryStream然后释放该内存(由调用者应用程序)?

调用者将使用动态LoadLibrary/FreeLibrary每个 DLL 调用。

我非常想要一个示例代码。希望我不要太粗鲁。

注 1:调用者应用程序不知道输出大小,并假设它无法指定 MAX buff 大小。

注 2:我不确定我的 DLL 签名。如果我做错了,请原谅我。我正在寻找一种运行良好的模式(也许不仅适用于 Delphi,也适用于 C++/C# 调用者 = 对我来说是额外的奖励)


稍微不同的方法是将每个内存流包装为 IStream,并传递生成的接口引用。所以,从 DLL 的角度来看:

uses
  System.SysUtils, System.Classes, Vcl.AxCtrls;

procedure DoProcess(InStream, OutStream: TStream);
begin
  //...do the actual processing here
end;

//wrapper export
procedure Process(AInStream: IStream; out AOutStream: IStream); safecall;
var
  InStream, OutStream: TStream;
begin
  InStream := TOleStream.Create(AInStream);
  try
    OutStream := TMemoryStream.Create;
    try
      DoProcess(InStream, OutStream);
      AOutStream := TStreamAdapter.Create(OutStream, soOwned);
    except
      OutStream.Free;
      raise;
    end;
  finally
    InStream.Free;
  end;
end;

就我个人而言,我也喜欢使用 safecall,因为这是一种实现异常安全的简单方法,但我想这是一个品味问题。

Edit

上述的一个变体是让调用者提供要读取的流and要写入的流:

//wrapper export
procedure Process(AInStream, AOutStream: IStream); safecall;
var
  InStream, OutStream: TStream;
begin
  InStream := TOleStream.Create(AInStream);
  try
    OutStream := TOleStream.Create(AOutStream);
    try
      DoProcess(InStream, OutStream);
    finally
      OutStream.Free;
    end;
  finally
    InStream.Free;
  end;
end;

EXE 端可能看起来像这样:

//wrapper import
type
  TDLLProcessProc = procedure(AInStream, AOutStream: IStream); safecall;

procedure Process(AInStream, AOutStream: TStream);
var
  InStream, OutStream: IStream;
  DLLProc: TDLLProcessProc;
  Module: HMODULE;
begin
  InStream := TStreamAdapter.Create(AInStream, soReference);
  OutStream := TStreamAdapter.Create(AOutStream, soReference);
  Module := LoadLibrary(MySuperLib);
  if Module = 0 then RaiseLastOSError;
  try
    DLLProc := GetProcAddress(Module, 'Process');
    if @DLLProc = nil then RaiseLastOSError;
    DLLProc(InStream, OutStream);
  finally
    FreeLibrary(Module);
  end;
end;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将内存流从我的应用程序传递到 DLL 或从 DLL 检索内存流? 的相关文章

随机推荐