如何将在 C 中分配的字符串返回给 Ada 并在 Ada 中释放它?

Pat*_*ick 5 c ada

这是这个问题的反面

我在 C 函数中分配了一个字符串(特别是由 cJSON 库),我想将它作为输出参数返回给 Ada 调用者,并从 Ada 中释放该字符串。

C 接口如下所示:

typedef struct
{
    int f1;
    int f2;
    // ...
} A;

int Dump_Record(const A& rec, char** outstr);
Run Code Online (Sandbox Code Playgroud)

Dump_Record函数将 outstr 设置为 返回的值cJSON_Print,它通过 分配一个字符串malloc

应如何指定 Ada 绑定以及如何检索输出字符串并在 Ada 中正确解除分配?

Luc*_*tia 7

下面显示了用于返回 achar **作为返回类型和输出 Ada 参数的 Ada、C 和 GPR 文件。

with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.C.Strings; use Interfaces.C.Strings;

procedure Str is
   function Get_Str return chars_ptr with
     Import => True,
     Convention => C,
     External_Name => "get_str";

   procedure Get_Str (Str : in out chars_ptr) with
     Import => True,
     Convention => C,
     External_Name => "get_str2";

   Str  : chars_ptr := Get_Str;
   Str2 : chars_ptr := Null_Ptr;
begin
   Get_Str (Str2);

   Put ("==> " & Value (Str));
   Put ("==> " & Value (Str2));

   Free (Str);
   Free (Str2);
end Str;
Run Code Online (Sandbox Code Playgroud)
with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.C.Strings; use Interfaces.C.Strings;

procedure Str is
   function Get_Str return chars_ptr with
     Import => True,
     Convention => C,
     External_Name => "get_str";

   procedure Get_Str (Str : in out chars_ptr) with
     Import => True,
     Convention => C,
     External_Name => "get_str2";

   Str  : chars_ptr := Get_Str;
   Str2 : chars_ptr := Null_Ptr;
begin
   Get_Str (Str2);

   Put ("==> " & Value (Str));
   Put ("==> " & Value (Str2));

   Free (Str);
   Free (Str2);
end Str;
Run Code Online (Sandbox Code Playgroud)
project Str is
   for Languages use ("C", "Ada");
   for Source_Dirs use (".");
   for Exec_Dir use ".";
   for Main use ("str.adb");
end Str;
Run Code Online (Sandbox Code Playgroud)

gprbuild -P str.

因此,要在 Ada 中实现您的功能:

package C renames Interfaces.C;

type A is
   record
      F1, F2 : C.int;
   end record with
     Convention => C;

   function Dump_Record (Rec : aliased A; Out_Str : out chars_ptr) return C.int with
     Import => True,
     Convention => C,
     External_Name => "Dump_Record";
Run Code Online (Sandbox Code Playgroud)

显然, Rec 参数需要别名,以便编译器知道它是 C 中的引用,并且不会将它重新分配到其他地方,即辅助堆栈。

  • 我不确定,但是鉴于 [RM B.3.1 (55)](http://www.ada-auth.org/standards/12rm/html/RM-B- 3-1.html#p55)? (2认同)
  • 它将与 GNAT 一起使用,因为 GNAT 使用 malloc/free 进行 new/unchecked_deallocation,这将与 C 应用程序相匹配。如果另一个编译器不使用 malloc/free 那么这可能不起作用。 (2认同)