Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a C-Function which takes a structure as argument

Tags:

c

ada

I'm stuck on this problem that I thought was simple. I have a structure definition and a function that takes an instance of this structure. How can I call this function in Ada? This is an example code:

defines.h :

typedef struct cartesian_t
{
    float x;
    float y;
    float z;
} cartesian_t;

void debug_cartesian(struct cartesian_t t);

defines.c

void debug_cartesian(struct cartesian_t t)
{
    printf("%f, %f, %f\n", t.x, t.y, t.z);
}

main.adb

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

procedure Main is
    type Cartesian_Record_Type is record
        X : C_Float;
        Y : C_Float;
        Z : C_Float;
    end record
    with
        Convention => C;
        
    procedure Debug_Cartesian(Cart : in Cartesian_Record_Type)
    with
        Import => True,
        Convention => C,
        External_Name => "debug_cartesian";


    T : Cartesian_Record_Type := (
        X => 5.0,
        Y => 1.0,
        Z => -1.0
    );
begin
    Debug_Cartesian(T);
end Main_Union;

The output is not what I expect. It should be "5.0, 1.0, -1.0" but something is clearly wrong in memory because I get random values. Like if is putting the data not where C expect them to be.

like image 836
Louis Etienne Avatar asked Apr 25 '21 14:04

Louis Etienne


1 Answers

There is an implementation advice in RM B.3 to always pass records by reference. GNAT, at least, follows this advice.

To circumvent this, you have two options:

  1. Pass the struct by reference in C:
 void debug_cartesian(struct cartesian_t *t);

or

  1. Pass the record by copy in Ada:
    end record
    with
       Convention => C_Pass_By_Copy;
like image 171
egilhh Avatar answered Oct 03 '22 05:10

egilhh