This is the inverse of this question.
I have a string allocated in a C function (specifically by the cJSON library) that I want to return to an Ada caller as an out parameter, and free the string from Ada.
The C interface looks like this:
typedef struct
{
int f1;
int f2;
// ...
} A;
int Dump_Record(const A& rec, char** outstr);
The Dump_Record
function sets outstr to the value returned by cJSON_Print
, which allocates a string via malloc
.
How should the Ada binding be specified and how can I retrieve the output string and properly deallocate it in Ada?
The following shows the Ada, C and GPR file for returning a char **
as a return type and as an out Ada parameter.
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;
#include <malloc.h>
#include <string.h>
const char *str = "Hello, Ada\n";
const char *str2 = "This is another C string!\n";
// As a return type.
const char *get_str (void) {
char *ptr = malloc (strlen (str) + 1);
strcpy (ptr, str);
return ptr;
}
// As a return / out parameter.
void get_str2 (char **ptr) {
*ptr = malloc (strlen (str2) + 1);
strcpy (*ptr, str2);
}
project Str is
for Languages use ("C", "Ada");
for Source_Dirs use (".");
for Exec_Dir use ".";
for Main use ("str.adb");
end Str;
Compile with gprbuild -P str
.
So to implement your function in 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";
Apparently, the Rec parameter needs to be aliased so the compiler knows it's a reference in C and doesn't re-allocate it somewhere else, i.e. secondary stack.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With