comp.lang.ada
 help / color / mirror / Atom feed
From: Jerry <lanceboyle@qwest.net>
Subject: Trouble writing Ada callback from C
Date: Fri, 11 Sep 2009 00:57:09 -0700 (PDT)
Date: 2009-09-11T00:57:09-07:00	[thread overview]
Message-ID: <e54f9d08-3083-4c98-974f-9695005679b3@x6g2000prc.googlegroups.com> (raw)

I have a problem with writing an Ada procedure, used as a callback
from C, in which one of the arguments is an output char * (in the C
version). The actual length of the returned "string" isn't known at
calling time, even though the caller apparently allocates 40
characters (see below). However, the actual number of characters
returned by the C version is less than 40.

My problem is how to pass probably a char_array back out which is the
correct length, but which length is not known at the time the Ada
callback is called from C.

Here is a highly shortened version of one of many things that I have
tried. I have not compiled or run this shortened version, but I
believe that it contains the essence of the longer version:


procedure geolocation_labeler
   (label    : out char_array;
    a_length : size_t);
pragma Convention(C, geolocation_labeler);

-- Highly shortened version.
procedure geolocation_labeler
   (label    : out char_array;
    a_length : size_t)
is
    direction_label : Unbounded_String;
begin
    Put_Line("a_length = " & a_length'img); -- for testing
    direction_label := To_Unbounded_String(" N"); -- not always length
2
    label := To_C(To_String(direction_label), False);
end geolocation_labeler;


Of course, this fails with:
raised CONSTRAINT_ERROR : blabla.adb:xxx length check failed

Note that the Put_Line always prints 40, passed by the C caller.



Here is a highly shortened version of the C callback. Note that PLINT
is just an integer.


/* Highly shortened version.*/
void
geolocation_labeler(char *label, PLINT length) {
    const char *direction_label;

    direction_label = " N";
    snprintf(label, length, "%s", direction_label);
    printf(label); /* for testing */
}


The printf(label) returns exactly <space>N (in this case) without \n.
In particular, it is only 2 characters, not 40. (Presumably, length
has a value of 40 here as well, although I have not tested that
assumption.)


I have tried things such as changing the type of label in the argument
list then declaring e.g.

label_as_char_array : aliased char_array := (0 .. whatever => ' ');
label_as_char_array_ptr : char_array_access;

then building the string in label_as_char_array, then doing

label_as_char_array_ptr := label_as_char_array'Unchecked_Access;

and then returning label_as_char_array_ptr. That also didn't work.


So how do I mimic the char * behavior of C when the length of the
output array is not known at call time?

Jerry



             reply	other threads:[~2009-09-11  7:57 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-09-11  7:57 Jerry [this message]
2009-09-11  8:24 ` Trouble writing Ada callback from C Ludovic Brenta
2009-09-11 20:38   ` sjw
2009-09-12  5:28   ` Jerry
2009-09-12  5:46     ` sjw
2009-09-16 23:06       ` Jerry
2009-09-12  8:44     ` Georg Bauhaus
2009-09-12 18:40 ` Vadim Godunko
2009-09-16 23:19   ` Jerry
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox