在Delphi XE7中制成的DLL返回在Delphi 2007中使用的字符串数组

皮疹

我正在尝试为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中返回数组的任何信息,或者我搜索错误。

有人可以帮忙吗?

提前致谢。

大卫·赫弗南(David Heffernan)

完全不能安全地调用该函数。您有以下问题:

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

最重要的是,您的功能try/finally实现不正确。您必须遵循众所周知的标准模式,这种模式在很多地方都可以看到。我认为这不是重复的地方。

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

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在Delphi XE7 Android中的Messagedlg

在Delphi XE7中使用NetEncoding对字符串进行Base64解码?

什么是Delphi XE7中的“ HotfixLevel 2”?

无法在Delphi XE7中删除控件

从Delphi XE7中的URL检索JSON数据

clientdataset中的Delphi XE7 + Rest / Json + Facebook组

使用Delphi XE7并行库

如何在Delphi XE7中设置“版本信息”?[Delphi设计问题]

在Delphi FireMonkey XE7中将字符串转换为日期时间时出错

使用多设备应用程序在Delphi xe7中的StatusBar中显示数据

使用 Delphi XE7 + SecureBridge 的 JIRA 查询

在Delphi XE7中将节点添加到IXMLNodeCollection

在Delphi XE7中,如何在变体点之后获取功能和属性建议?

Excel 2010自动化常数在Delphi XE7中不起作用

在delphi xe7中自定义FMX.InAppPurchase.Android单元

如何在Delphi XE7上的其他过程中执行TTakePhotoFromCameraAction?

Delphi 2007中使用Variant数组有什么要求?

字符串[80]与Delphi 7和Delphi XE4中的字符串之间的区别

在Delphi XE7中第二次在Android上打开表单时发生访问冲突

如何在用于多个平台的Delphi XE7应用程序中处理平台特定的代码?

Delphi 中的 Fortran DLL

在Delphi 7中调用C ++ DLL函数

Delphi XE7:如何使用System.JSON更改JSON值(相对于SuperObject)

使用Delphi XE7和Indy类创建亚马逊MWS签名

添加文件以在 Android 中部署时出错,使用 firemonkey delphi Xe7

Reg。使用Delphi XE7进行iOs移动应用程序开发的硬件要求

Delphi XE7使用EmptyParam通过OLE Auto打开Word2010文档

Delphi XE7智能指针

文字提示Delphi XE7