Ada sending byte buffer to c

Question

I'm having an issue with interfacing to C from ada. In particular I have this ada declaration:

type Byte is mod 256; pragma Convention (C, Byte);
type ByteStream is array (Interfaces.C.size_t range <>) of Byte;
    pragma Convention (C, ByteStream);
type VoidPointer is access all ByteStream;
type ByteBuffer is
    record
        data : VoidPointer;
        size : Interfaces.C.size_t;
    end record;
pragma Convention (C, ByteBuffer);
procedure Free is new Ada.Unchecked_Deallocation (ByteStream, VoidPointer);

and this C declaration:

struct ByteBuffer {
    unsigned char *data;
    size_t size;
};

and this ada import:

function My_Function (
    data : in ByteBuffer)
    return Interfaces.C.int;
pragma Import (C, My_Function, "my_function");

and this C declaration:

int my_function(struct ByteBuffer data);

And yet when I debug my code I find a size of (in one example) 110 on the ada side, but 0x7fffffffe750 on the c side. Why is my size_t being mangled? (Note: the data itself is also mangled, but hopefully fixing one will fix the other).


Show source
| C   | ada   2016-10-17 18:10 2 Answers

Answers ( 2 )

  1. 2016-10-17 18:10

    The in parameter in Ada can use either reference or copy, but it's compiler/structure size dependent.

    To force both parties to use pointers (the easiest thing to do here) you can do this:

    On the Ada side:

    function My_Function (
        data : access ByteBuffer)
        return Interfaces.C.int;
    pragma Import (C, My_Function, "my_function");
    

    And on the C side:

    int my_function(const struct ByteBuffer *data);
    

    Since ByteBuffer is a constrained array, another info passes: the boundaries which is a pointer (the whole pointer is a "fat" pointer). You could "skip" it on the C side by doing this:

    struct ByteBuffer {
        unsigned char *data;
        void *skipit;  // ignore this value
        size_t size;
    };
    

    To force Ada to pass by copy, you can use pragma Convention(C_Pass_By_Copy,ByteBuffer) after type declaration (Ada side)

  2. 2016-10-18 21:10

    Ada unbounded strings has a compiler dependent data mapping. In the one that I use I have checked that its starts with something (like a tag) that says about the size of the string and then comes the "normal" array of bytes. When you pass the buffer from C to Ada, this last one is going to take the lentgh of the unbounded array from the first elements of your C array. I don't known why you need your example, but if I suppose you are going to point arrays of already created data, you could declare ByteStream as a fixed legth array (lets say as big as your maximum size) because you are going to manage the real size with your "size" parameter. In other words, it has no sense that you have in ada the "size" parameter of your ByteBuffer record as it goes into the pointed unbounded string structure and can be extracted with the 'Length atribute.

◀ Go back