从Delphi 7中的C DLL接收一个字符串

Receive an array of string from a c++ DLL in Delphi 7

本文关键字:字符串 一个 Delphi 中的 DLL      更新时间:2023-10-16

我在C 中创建一个DLL,将在Delphi 7项目中使用。

这个问题与这个问题有关,在其中我提出两个函数ValidateGetToken,仅此问题现在它们将在C 中完成,并且字符串 GetToken产生的数组将发送回Delphi。

问题是我不知道如何在dll中创建将返回C 字符串数组的函数,而且我不知道如何将其存储在Delphi中。

该函数的声明如下:

function GetToken(Chain:string):Arrayofstring;

根据您的代码评论,Delphi代码期望该功能具有以下签名:

function GetToken(Chain: AnsiString): array of AnsiString;

您不能在C 中写下这样的功能。C 不知道Delphi字符串是什么,并且也不知道Delphi Dynamic Arrays是什么。两种类型都需要从Delphi的内存管理器中分配,您的C DLL无法访问。此外,C 不知道如何使用Delphi的register调用约定。

DLL接口的设计较差。除非设计师的意图排除所有其他语言,否则DLL绝不应使用特定于语言的类型。(在这种情况下,即使是同一语言的后期版本也被排除在外,因为AnsiString在Delphi 2009中更改了Delphi 7无法正确处理的更多元数据。)选择最安全的呼叫约定通常是stdcall。这就是Windows API中的所有内容。

更好的接口将使用所有语言共有的类型,它将决定可普遍访问的内存管理。有几种常见的方法可以做到这一点。例如:

  • 将字符串作为字符的简单终止阵列返回 - Delphi中的PAnsiCharchar*在C 中。DLL为字符串分配缓冲区,并为这些字符串的数组分配一个缓冲区。当使用数组和字符串完成主机应用程序时,它调用了由DLL导出的另一个功能,其中DLL释放了分配的内存。这是例如FormatMessage使用的模型;当主机程序完成带有消息字符串的程序时,它将调用LocalFree

    type
      PStringArray = ^TStringArray;
      TStringArray = array[0..Pred(MaxInt) div SizeOf(PAnsiChar)] of PAnsiChar;
    function GetToken(Char: PAnsiChar): PStringArray; stdcall;
    procedure FreeStringArray(StringArray: PStringArray); stdcall;
    
    char** __stdcall GetToken(char const* Chain);
    void __stdcall FreeStringArray(char** StringArray);
    
  • 使用COM返回BSTR对象的SafeArray。它类似于以前的技术,但是内存管理是由COM定义的,而不是由您的DLL定义,因此,界面的任何一方都需要定义的内容较少。

  • 将回调函数传递到DLL,因此DLL不再返回一系列字符串,而是为其标识的每个字符串调用一次函数。然后,您不必定义任何数组的外观,每个字符串的寿命只能是回调调用的寿命 - 如果主机应用程序想要副本,则可以这样做。新功能签名看起来像这样:

    type
      TTokenCallback = procedure(Token: PAnsiChar); stdcall;
    procedure GetToken(Chain: PAnsiChar; ProcessToken: TTokenCallback); stdcall;
    
    typedef void (__stdcall* TokenCallback)(char const* Token);
    void __stdcall GetToken(char const* Chain, TokenCallback ProcessToken);
    

如果您不是设计DLL接口的人,那么您需要依靠做并更改它的人,以便更容易访问非delphi code。如果您不能这样做,那么最终的选择是在Delphi中写下DLL,将您的DLL包裹以将参数按摩到各个方面都可以理解的东西。

相关文章: