gpt4 book ai didi

delphi - Delphi XE7 中创建的 DLL 返回字符串数组以在 Delphi 2007 中使用

转载 作者:行者123 更新时间:2023-12-02 19:36:09 26 4
gpt4 key购买 nike

我正在尝试为我们在 Delphi 2007 中的项目制作一个使用 XE7 中的 TAmazonStorageService 组件的 dll。

但是,我遇到了几次内存泄漏,或者数组的所有索引都返回最后一个字符串。

这是我的功能:

function ListBuckets(const PrivateKEY: PAnsiChar; const PublicKEY: PAnsiChar; 
out ArrayBuckets: TArray<PAnsiChar>;
out Error: PAnsiChar): Boolean; stdcall;
var
AmazonConn: TAmazonConnectionInfo;
AmazonS3: TAmazonStorageService;
ResponseInfo: TCloudResponseInfo;
BucketsList: TStrings;

I: Integer;
begin
Result := True;

AmazonConn := TAmazonConnectionInfo.Create(nil);

AmazonConn.AccountName := string(PublicKEY); { AccessKeyID }
AmazonConn.AccountKey := string(PrivateKEY); { SecretAccessKeyID }

AmazonS3 := TAmazonStorageService.Create(AmazonConn);

ResponseInfo := TCloudResponseInfo.Create;

Error := '';

try
BucketsList := AmazonS3.ListBuckets(ResponseInfo);
if not Assigned(BucketsList) then
begin
Result := False;

Error := PAnsiChar(AnsiString(ResponseInfo.StatusMessage));
end
else
begin
SetLength(ArrayBuckets, BucketsList.Count);

for I := 0 to BucketsList.Count - 1 do
ArrayBuckets[I] := PAnsiChar(AnsiString(BucketsList.Strings[I]));
end;
finally
BucketsList.Free;
ResponseInfo.Free;
AmazonS3.Free;
AmazonConn.Free;
end;
end;

exports ListBuckets;

这是我“尝试”使用此功能的方式。需要在 Delphi XE7 和 Delphi 2007 中工作。

type
TAnsiCharArray = array of PAnsiChar;

function ListBuckets(const PrivateKEY: PAnsiChar; const PublicKEY: PAnsiChar;
out ArrayBuckets: TAnsiCharArray;
out MensagemErro: PAnsiChar): Boolean; stdcall;
external 'Test.dll';

function ListBucketsDelphi(const PrivateKEY: string; const PublicKEY: string;
out StringListBuckets: TStringList;
out Error: string): Boolean;
var
vAnsiPrivateKEY: PAnsiChar;
vAnsiPublicKEY: PAnsiChar;
vAnsiError: PAnsiChar;
vStringArray: TAnsiCharArray;
I: Integer;
begin
{$IFDEF UNICODE}
vAnsiPrivateKEY := PAnsiChar(RawByteString(PrivateKEY));
vAnsiPublicKEY := PAnsiChar(RawByteString(PublicKEY));
{$ELSE}
vAnsiPrivateKEY := PAnsiChar(PrivateKEY);
vAnsiPublicKEY := PAnsiChar(PublicKEY);
{$ENDIF}

//StringListBuckets need to be created before...

Result := ListBuckets(vAnsiPrivateKEY, vAnsiPublicKEY, vStringArray, vAnsiMensagemErro);

if not (Result) then
Error := string(vAnsiError);

try
if Result then
begin
for I := Low(vStringArray) to High(vStringArray) do
StringListBckets.Append(vStringArray[I]);
end;
except
Result := False;
Error := '"StringListBuckets" not created.';
end;
end;

我搜索了一下,但没有发现有关在 unicode dll 中返回数组的信息,或者也许我搜索错误。

有人可以帮忙吗?

提前致谢。

最佳答案

该函数根本无法安全调用。您遇到以下问题:

  • 除非您共享内存管理器,否则您将在一个模块中分配内存,并在另一个模块中销毁它。这是违反规则的。
  • 您返回的字符串指针(您的两个 out 参数)在函数返回时无效。换句话说,一旦函数返回,这些指针所指向的东西就不再存在了。
  • 您正在跨模块边界传递 Delphi 动态数组。 Delphi 动态数组对于互操作无效。

最重要的是,您的函数 try/finally 的实现不正确。您必须遵循众所周知的标准模式,这种模式在无数地方都可以看到。我认为这里不应该重复这一点。

您需要彻底重新设计。一些选项:

  1. 让调用者分配内存,并将其传递给 DLL 进行填充。这会限制您预先决定分配多少内存。
  2. 使用基于枚举的方法。调用 DLL 以分配保存状态的不透明指针。然后重复调用另一个函数,传递不透明指针,并生成一个字符串。当没有更多数据时,调用终结函数进行整理。使用 WideString 返回字符串,因为它是从共享堆分配的。
  3. 将返回的信息序列化为例如JSON。然后以单个字符串返回该值,再次使用 WideString 来利用共享 COM 堆。
  4. 让可执行文件向 DLL 提供回调函数。然后 DLL 可以分配一个数组并将其传递给回调函数。回调函数必须获取数组的副本。
  5. 声明一个封装可保存数据的结构的接口(interface)。将该接口(interface)传递给 DLL。接口(interface)可以跨模块边界安全使用。
  6. 使用 COM 安全数组返回数组。
  7. 避免使用单独的 DLL,并在 Delphi 2007 模块中编写所有内容。

关于delphi - Delphi XE7 中创建的 DLL 返回字符串数组以在 Delphi 2007 中使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26288559/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com