comp.lang.ada
 help / color / mirror / Atom feed
* C array to Ada pointer to unconstrained array without copying memory
@ 2003-10-07 14:43 Duncan Sands
  2003-10-07 18:30 ` tmoran
                   ` (3 more replies)
  0 siblings, 4 replies; 28+ messages in thread
From: Duncan Sands @ 2003-10-07 14:43 UTC (permalink / raw)
  To: comp.lang.ada

Greetings.  Given a C pointer Ptr to a type T (which points to a block of memory
containing a C array of T's) and the length of the array Length, there are various
tricks for getting an Ada array of the right size (defined on the stack - important!)
that uses the block of memory to hold the array data, i.e. no copying required.

For example,

type Ada_Array is array (Positive range <>) of T;

...

[have Length and Ptr]

subtype Array2 is Ada_Array (1 .. Length);

X : Array2;
for X'Address use Ptr; -- ok, Ptr should be of type System'Address, but hey!

And then you can make use of X.  However being defined on the stack, it
can be quite awkward to use.  It would be nice to have the same thing but
with X dynamically allocated.  For example,

type Ada_Array_Pointer is access Ada_Array;

...

[have Length and Ptr]

X_Ptr : Ada_Array_Pointer;

[do some clever stuff to set up X_Ptr to point to an array where the
data is given by Ptr, and the bounds are somewhere else, but where? :)]

[Pass X_Ptr around and dereference it etc.]

The problem is the bounds of course.  For example, GNAT usually uses
fat pointers, consisting of two normal pointers where one points to the
data, and the other to the bounds.  So the "clever stuff" will need to
allocate some memory to hold the bounds and set up the fat pointer
appropriately.

Does anyone know a good way to do this?  The solution only needs to
work with GNAT.  I appreciate that deallocating the pointer may need
to be handled specially.

All the best,

Duncan.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-07 14:43 C array to Ada pointer to unconstrained array without copying memory Duncan Sands
@ 2003-10-07 18:30 ` tmoran
  2003-10-07 19:24   ` Duncan Sands
                     ` (2 more replies)
  2003-10-07 20:00 ` Jeffrey Carter
                   ` (2 subsequent siblings)
  3 siblings, 3 replies; 28+ messages in thread
From: tmoran @ 2003-10-07 18:30 UTC (permalink / raw)


>subtype Array2 is Ada_Array (1 .. Length);
>
>X : Array2;
>for X'Address use Ptr; -- ok, Ptr should be of type System'Address, but hey!
>
>And then you can make use of X.  However being defined on the stack, it
>can be quite awkward to use.
   I don't understand.  Nothing is defined on, or off, the stack here.
You are saying that X is at location 12345 (or whatever) in RAM.
Whether X happens to be in the same area as the stack depends on
whether (System.Address_to_Access_Conversions .To_Address of) Ptr
happens to point into the stack or not.

>It would be nice to have the same thing but with X dynamically allocated.
  If Ptr points into your program's heap memory, that's where X will be.
Or do you mean C is allocating memory, and setting its memory allocation
structures, and you want an Ada Access type, and Ada's memory allocation
structures, to be set as if that memory was allocated by an Ada "new"?

>The problem is the bounds of course.
  If a call to C gave you an address and a length, then those, not a
constrained array, are what you have to work with.  Just as in C,
you'll have to write things like
  if Index in 1 .. Length then
    Y := X(Index);
  else
    raise Constraint_Error;
  end if;

>For example, GNAT usually uses
>fat pointers, consisting of two normal pointers where one points to the
>data, and the other to the bounds.  So the "clever stuff" will need to
>allocate some memory to hold the bounds and set up the fat pointer
>appropriately.
  So you're talking about using embedded assembly language to fake out the
compiler?  If it's the only way to get to the moon, someone will have to
put themselves on top of an enormous can of explosives and light the
outlets.  Most real problems, however, can be solved in less dangerous
ways.  What's the real problem you are trying to solve here?



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-07 18:30 ` tmoran
@ 2003-10-07 19:24   ` Duncan Sands
  2003-10-08  0:02   ` sk
       [not found]   ` <3F83540E.5000302@myob.com>
  2 siblings, 0 replies; 28+ messages in thread
From: Duncan Sands @ 2003-10-07 19:24 UTC (permalink / raw)
  To: tmoran, comp.lang.ada

On Tuesday 07 October 2003 20:30, tmoran@acm.org wrote:
> >subtype Array2 is Ada_Array (1 .. Length);
> >
> >X : Array2;
> >for X'Address use Ptr; -- ok, Ptr should be of type System'Address, but
> > hey!
> >
> >And then you can make use of X.  However being defined on the stack, it
> >can be quite awkward to use.
>
>    I don't understand.  Nothing is defined on, or off, the stack here.

The bounds of X are on the stack if this is in a procedure; sorry I wasn't
clear here (in my head X was declared as a local variable in a procedure,
and that leaked out into the email).

> You are saying that X is at location 12345 (or whatever) in RAM.

That has no meaning - since (GNAT) X has two parts: data and bounds.
The data is at location 12345, the bounds are somewhere else.

> Whether X happens to be in the same area as the stack depends on
> whether (System.Address_to_Access_Conversions .To_Address of) Ptr
> happens to point into the stack or not.
>
> >It would be nice to have the same thing but with X dynamically allocated.
>
>   If Ptr points into your program's heap memory, that's where X will be.
> Or do you mean C is allocating memory, and setting its memory allocation
> structures, and you want an Ada Access type, and Ada's memory allocation
> structures, to be set as if that memory was allocated by an Ada "new"?

Not really.  The fact the memory wasn't allocated by Ada will only be
problematic if it is deallocated by Ada.

> >The problem is the bounds of course.
>
>   If a call to C gave you an address and a length, then those, not a
> constrained array, are what you have to work with.  Just as in C,
> you'll have to write things like
>   if Index in 1 .. Length then
>     Y := X(Index);
>   else
>     raise Constraint_Error;
>   end if;

This may be what you should do - but I'm not asking that.  I'm asking
how to do something unwise, as in your next paragraph.

> >For example, GNAT usually uses
> >fat pointers, consisting of two normal pointers where one points to the
> >data, and the other to the bounds.  So the "clever stuff" will need to
> >allocate some memory to hold the bounds and set up the fat pointer
> >appropriately.
>
>   So you're talking about using embedded assembly language to fake out the
> compiler?  If it's the only way to get to the moon, someone will have to
> put themselves on top of an enormous can of explosives and light the
> outlets.  Most real problems, however, can be solved in less dangerous
> ways.  What's the real problem you are trying to solve here?

Exactly.  Well, there need be no assembly language, just some unchecked
conversions.  As to why, let's just say I enjoy living dangerously.  It seems to
me that such a trick is possible (if not desirable, and not portable between
compilers) - and the degree of danger is not clear to me.  If it can be done,
I would like to know - that doesn't mean I'm going to do it.  Anyway, someone
with a good knowledge of GNAT internals should be able to say if it would work
like a charm or the opposite.

Thanks for your help,

Duncan.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-07 14:43 C array to Ada pointer to unconstrained array without copying memory Duncan Sands
  2003-10-07 18:30 ` tmoran
@ 2003-10-07 20:00 ` Jeffrey Carter
  2003-10-07 20:39   ` Duncan Sands
  2003-10-07 20:53 ` Chad R. Meiners
  2003-10-08 14:07 ` Steve Adams
  3 siblings, 1 reply; 28+ messages in thread
From: Jeffrey Carter @ 2003-10-07 20:00 UTC (permalink / raw)


Duncan Sands wrote:

> [have Length and Ptr]
> 
> subtype Array2 is Ada_Array (1 .. Length);
> 
> X : Array2;
> for X'Address use Ptr; -- ok, Ptr should be of type System'Address, but hey!

You should also have

pragma Import (Ada, X);

to avoid initializing X. But this may not provide usable bounds for X. 
If, for example, your compiler stores the bounds in memory just before 
the 1st element of X, this may result in garbage for the bounds of X.

The general technique is to use Ptr as an access value to something as 
large or larger than Length can ever be, then immediately take a slice 
and pass it elsewhere. Slicing generates the bounds information. The 
following compiles:

procedure Bound_Generation is
    type T is new Integer;

    type Real is array (Positive range <>) of T;
    subtype Huge is Real (Positive);

    type Huge_Ptr is access all Huge;
    pragma Convention (C, Huge_Ptr);

    X_Ptr  : Huge_Ptr;
    Length : Positive;

    procedure Deal_With_X (X : in Real) is
    begin -- Deal_With_X
       null;
    end Deal_With_X;
begin -- Bound_Generation
    -- Get X_Ptr and Length from C
    Deal_With_X (X => X_Ptr (1 .. Length) );
end Bound_Generation;

> And then you can make use of X.  However being defined on the stack, it
> can be quite awkward to use.  It would be nice to have the same thing but
> with X dynamically allocated.  For example,

There is generally no need for a pointer to X; I'd have to know more 
about what you're trying to do to understand why you say you want one. 
With GNAT, you could use 'Unrestricted_Access on X within Deal_With_X to 
obtain such a pointer. Or, instead of calling a subprogram, you could do 
something like:

declare
    type Real_Ptr is access all Real;

    X : Real_Ptr;

    Result : aliased Real := X_Ptr (1 .. Length);
begin
    X := Result'Access;
    -- Deal with X here
end;

-- 
Jeff Carter
"Your mother was a hamster and your father smelt of elderberries."
Monty Python & the Holy Grail
06




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-07 20:00 ` Jeffrey Carter
@ 2003-10-07 20:39   ` Duncan Sands
  2003-10-08  1:27     ` Jeffrey Carter
  0 siblings, 1 reply; 28+ messages in thread
From: Duncan Sands @ 2003-10-07 20:39 UTC (permalink / raw)
  To: Jeffrey Carter, comp.lang.ada

Hi Jeff, thanks for your reply.

> You should also have
>
> pragma Import (Ada, X);
>
> to avoid initializing X. But this may not provide usable bounds for X.
> If, for example, your compiler stores the bounds in memory just before
> the 1st element of X, this may result in garbage for the bounds of X.
>
> The general technique is to use Ptr as an access value to something as
> large or larger than Length can ever be, then immediately take a slice
> and pass it elsewhere. Slicing generates the bounds information. The
> following compiles:
>
> procedure Bound_Generation is
>     type T is new Integer;
>
>     type Real is array (Positive range <>) of T;
>     subtype Huge is Real (Positive);
>
>     type Huge_Ptr is access all Huge;
>     pragma Convention (C, Huge_Ptr);
>
>     X_Ptr  : Huge_Ptr;
>     Length : Positive;
>
>     procedure Deal_With_X (X : in Real) is
>     begin -- Deal_With_X
>        null;
>     end Deal_With_X;
> begin -- Bound_Generation
>     -- Get X_Ptr and Length from C
>     Deal_With_X (X => X_Ptr (1 .. Length) );
> end Bound_Generation;

Right.  With GNAT there is no problem with the method I mentioned, but this method
indeed seems more portable.  A few other methods are discussed on the page
http://www.adapower.com/lang/accessmem.html

> > And then you can make use of X.  However being defined on the stack, it
> > can be quite awkward to use.  It would be nice to have the same thing but
> > with X dynamically allocated.  For example,
>
> There is generally no need for a pointer to X; I'd have to know more
> about what you're trying to do to understand why you say you want one.

I'm a bit surprised you ask.  Your comment is analogous to "there is
generally no need to use pointers to strings".  And indeed, you often
don't need them, but there are plenty of legitimate, not to say essential
uses for them.  I would like to pass a pointer to X all around my program.

> With GNAT, you could use 'Unrestricted_Access on X within Deal_With_X to
> obtain such a pointer. 

Woah!  Not so!  (Or at least so it seems to me).  This pointer to X will be
a fat pointer, with one part pointing the the data (i.e. X_Ptr) - and this can
be used after Deal_With_X returns -, and another part pointing to the bounds.
And where are these bounds stored?  Right, on the stack (or some other
convenient temporary place), and that bit of memory will go away once
Deal_With_X returns.  So if I use Unrestricted_Access to get a pointer
to X and stick it in (for example) a global variable, then accessing X
through it after returning from Deal_With_X will lead to swift punishment.

> Or, instead of calling a subprogram, you could do
> something like:
>
> declare
>     type Real_Ptr is access all Real;
>
>     X : Real_Ptr;
>
>     Result : aliased Real := X_Ptr (1 .. Length);
> begin
>     X := Result'Access;
>     -- Deal with X here
> end;

But I would like

-- Deal with X here

(after the end;).

And this seems tricky.

All the best,

Duncan.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-07 14:43 C array to Ada pointer to unconstrained array without copying memory Duncan Sands
  2003-10-07 18:30 ` tmoran
  2003-10-07 20:00 ` Jeffrey Carter
@ 2003-10-07 20:53 ` Chad R. Meiners
  2003-10-07 21:24   ` Duncan Sands
  2003-10-08 14:07 ` Steve Adams
  3 siblings, 1 reply; 28+ messages in thread
From: Chad R. Meiners @ 2003-10-07 20:53 UTC (permalink / raw)



"Duncan Sands" <baldrick@free.fr> wrote in message
news:mailman.37.1065537708.25614.comp.lang.ada@ada-france.org...
> The problem is the bounds of course.  For example, GNAT usually uses
> fat pointers, consisting of two normal pointers where one points to the
> data, and the other to the bounds.  So the "clever stuff" will need to
> allocate some memory to hold the bounds and set up the fat pointer
> appropriately.
>
> Does anyone know a good way to do this?  The solution only needs to
> work with GNAT.  I appreciate that deallocating the pointer may need
> to be handled specially.

See http://www.adapower.com/lang/accessmem.html method 1c using
Address_To_Access_Conversions.

Page for strings, but it should work for any array type as long as you have
the representation correct.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-07 20:53 ` Chad R. Meiners
@ 2003-10-07 21:24   ` Duncan Sands
  2003-10-07 22:44     ` C array to Ada pointer to unconstrained array without copyingmemory Chad R. Meiners
  2003-10-08  2:14     ` C array to Ada pointer to unconstrained array without copying memory Robert I. Eachus
  0 siblings, 2 replies; 28+ messages in thread
From: Duncan Sands @ 2003-10-07 21:24 UTC (permalink / raw)
  To: Chad R. Meiners, comp.lang.ada

On Tuesday 07 October 2003 22:53, Chad R. Meiners wrote:
> "Duncan Sands" <baldrick@free.fr> wrote in message
> news:mailman.37.1065537708.25614.comp.lang.ada@ada-france.org...
>
> > The problem is the bounds of course.  For example, GNAT usually uses
> > fat pointers, consisting of two normal pointers where one points to the
> > data, and the other to the bounds.  So the "clever stuff" will need to
> > allocate some memory to hold the bounds and set up the fat pointer
> > appropriately.
> >
> > Does anyone know a good way to do this?  The solution only needs to
> > work with GNAT.  I appreciate that deallocating the pointer may need
> > to be handled specially.
>
> See http://www.adapower.com/lang/accessmem.html method 1c using
> Address_To_Access_Conversions.
>
> Page for strings, but it should work for any array type as long as you have
> the representation correct.

Thanks Chad, but in fact that was not the question :)
The method you refer to makes it easy to get a local
variable with the right bounds, but that is not enough for me!

Here is an example.

Suppose I get the result in a local array X with the right bounds:

type Array_Type is (Positive range <>) of Something;
type Array_Pointer is access Array_Type;

...
get data and length from C
...

X : Array_Type (1 .. length);
for X'Address use data; -- or another method

So far so good.  Now suppose I do:

Y : Array_Pointer := new Array_Type' (X);  -- (*)

The object I want is Y.  What is the problem?  The problem
is that line (*) involves allocating memory and copying the
data from X to that memory.  I would like to end up with Y
without performing the copy (and without reallocating
memory for the array data).

All the best,

Duncan.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copyingmemory
  2003-10-07 21:24   ` Duncan Sands
@ 2003-10-07 22:44     ` Chad R. Meiners
  2003-10-07 22:52       ` Chad R. Meiners
  2003-10-08  2:14     ` C array to Ada pointer to unconstrained array without copying memory Robert I. Eachus
  1 sibling, 1 reply; 28+ messages in thread
From: Chad R. Meiners @ 2003-10-07 22:44 UTC (permalink / raw)



"Duncan Sands" <duncan.sands@math.u-psud.fr> wrote in message
news:mailman.41.1065561795.25614.comp.lang.ada@ada-france.org...
> On Tuesday 07 October 2003 22:53, Chad R. Meiners wrote:
> > "Duncan Sands" <baldrick@free.fr> wrote in message
> > news:mailman.37.1065537708.25614.comp.lang.ada@ada-france.org...
> >
> > > The problem is the bounds of course.  For example, GNAT usually uses
> > > fat pointers, consisting of two normal pointers where one points to
the
> > > data, and the other to the bounds.  So the "clever stuff" will need to
> > > allocate some memory to hold the bounds and set up the fat pointer
> > > appropriately.
> > >
> > > Does anyone know a good way to do this?  The solution only needs to
> > > work with GNAT.  I appreciate that deallocating the pointer may need
> > > to be handled specially.
> >
> > See http://www.adapower.com/lang/accessmem.html method 1c using
> > Address_To_Access_Conversions.
> >
> > Page for strings, but it should work for any array type as long as you
have
> > the representation correct.
>
> Thanks Chad, but in fact that was not the question :)
> The method you refer to makes it easy to get a local
> variable with the right bounds, but that is not enough for me!
>
> Here is an example.
>
> Suppose I get the result in a local array X with the right bounds:
>
> type Array_Type is (Positive range <>) of Something;
> type Array_Pointer is access Array_Type;
>
> ...
> get data and length from C
> ...
>
> X : Array_Type (1 .. length);
> for X'Address use data; -- or another method
>
> So far so good.  Now suppose I do:
>
> Y : Array_Pointer := new Array_Type' (X);  -- (*)
>
> The object I want is Y.  What is the problem?  The problem
> is that line (*) involves allocating memory and copying the
> data from X to that memory.  I would like to end up with Y
> without performing the copy (and without reallocating
> memory for the array data).

declare
    C_Data_Ptr       :  Systems.Address := To_Address(My_C_Ptr);
    C_Data_Length :  Natural   := ...;

    type My_Ada_Type_Element is ...;
    type My_Ada_Array is array(Natural range <>) of My_Ada_Type_Element;

    subtype My_C_Data_As_An_Ada_Array_Type is
My_Ada_Array(1..C_Data_Length);
    package My_Converter is new
Address_To_Access_Conversions(My_C_Data_As_An_Ada_Array_Type);

    C_Data_In_Ada : My_Ada_Array renames
My_Converter.To_Pointer(C_Data_Ptr).all;
    -- No copying of the array done, but the array dope that you want is
built from the subtype information.
begin
...
end;





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copyingmemory
  2003-10-07 22:44     ` C array to Ada pointer to unconstrained array without copyingmemory Chad R. Meiners
@ 2003-10-07 22:52       ` Chad R. Meiners
  2003-10-08  9:20         ` Duncan Sands
  0 siblings, 1 reply; 28+ messages in thread
From: Chad R. Meiners @ 2003-10-07 22:52 UTC (permalink / raw)



"Chad R. Meiners" <crmeiners@hotmail.com> wrote in message
news:blvfo6$q6s$1@msunews.cl.msu.edu...
> declare
>     C_Data_Ptr       :  Systems.Address := To_Address(My_C_Ptr);
>     C_Data_Length :  Natural   := ...;
>
>     type My_Ada_Type_Element is ...;
>     type My_Ada_Array is array(Natural range <>) of My_Ada_Type_Element;
>
>     subtype My_C_Data_As_An_Ada_Array_Type is
> My_Ada_Array(1..C_Data_Length);
>     package My_Converter is new
> Address_To_Access_Conversions(My_C_Data_As_An_Ada_Array_Type);
>     C_Data_In_Ada : My_Ada_Array renames
> My_Converter.To_Pointer(C_Data_Ptr).all;
>     -- No copying of the array done, but the array dope that you want is
> built from the subtype information.
> begin
> ...
> end;

I should probably add that you can just get the pointer with

My_Ada_Array_Ptr : My_Converter.Object_Pointer :=
My_Converter.To_Pointer(C_Data_Ptr);

I believe that this satisfies your needs?
-CRM






^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-07 18:30 ` tmoran
  2003-10-07 19:24   ` Duncan Sands
@ 2003-10-08  0:02   ` sk
       [not found]   ` <3F83540E.5000302@myob.com>
  2 siblings, 0 replies; 28+ messages in thread
From: sk @ 2003-10-08  0:02 UTC (permalink / raw)
  To: comp.lang.ada

duncan.sands@math.u-psud.fr:
 > ... <snip> ...

package "Interfaces.C.Pointers" seems to provide the
functionality required in discussion so far.


-- 
-------------------------------------------------
-- Merge vertically for real address
--
--     s n p @ t . o
--      k i e k c c m
-------------------------------------------------




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-07 20:39   ` Duncan Sands
@ 2003-10-08  1:27     ` Jeffrey Carter
  0 siblings, 0 replies; 28+ messages in thread
From: Jeffrey Carter @ 2003-10-08  1:27 UTC (permalink / raw)


Duncan Sands wrote:

> I'm a bit surprised you ask.  Your comment is analogous to "there is 
> generally no need to use pointers to strings".  And indeed, you often
>  don't need them, but there are plenty of legitimate, not to say
> essential uses for them.  I would like to pass a pointer to X all
> around my program.

Every time I've seen an example that needs pointers to String, it didn't
need pointers to String. Lots of people like to use pointers when
they're not necessary; the fact that you'd like to pass a pointer to X
all around your program doesn't mean you need to.

-- 
Jeff Carter
"My name is Jim, but most people call me ... Jim."
Blazing Saddles
39




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-07 21:24   ` Duncan Sands
  2003-10-07 22:44     ` C array to Ada pointer to unconstrained array without copyingmemory Chad R. Meiners
@ 2003-10-08  2:14     ` Robert I. Eachus
  2003-10-08  9:27       ` Duncan Sands
  1 sibling, 1 reply; 28+ messages in thread
From: Robert I. Eachus @ 2003-10-08  2:14 UTC (permalink / raw)


Duncan Sands wrote:

> So far so good.  Now suppose I do:
> 
> Y : Array_Pointer := new Array_Type' (X);  -- (*)
> 
> The object I want is Y.  What is the problem?  The problem
> is that line (*) involves allocating memory and copying the
> data from X to that memory.  I would like to end up with Y
> without performing the copy (and without reallocating
> memory for the array data).

What is wrong with:

Y: Array_Type;
for Y'Address use X'Address;

..if you want X and Y to be two different views of the same memory.
Notice that there is no need for an explicit pointer here, but if X is a 
  pointer as in your example, you may want to do:

Y: Array_Type;
for Y'Address use X.all'Address;

Oh, and if there is initialization for the elements of Array_Type you 
may want to add a pragma Import; to turn off initialization.
-- 
                                          Robert I. Eachus

"Quality is the Buddha. Quality is scientific reality. Quality is the 
goal of Art. It remains to work these concepts into a practical, 
down-to-earth context, and for this there is nothing more practical or 
down-to-earth than what I have been talking about all along...the repair 
of an old motorcycle."  -- from Zen and the Art of Motorcycle 
Maintenance by Robert Pirsig




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
       [not found]   ` <3F83540E.5000302@myob.com>
@ 2003-10-08  9:18     ` Duncan Sands
  0 siblings, 0 replies; 28+ messages in thread
From: Duncan Sands @ 2003-10-08  9:18 UTC (permalink / raw)
  To: sk, comp.lang.ada

On Wednesday 08 October 2003 02:02, sk wrote:
> duncan.sands@math.u-psud.fr:
>  > ... <snip> ...
>
> package "Interfaces.C.Pointers" seems to provide the
> functionality required in discussion so far.

Actually not.  It will give you an array, but not an array stored
in the heap.

Ciao,

Duncan.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copyingmemory
  2003-10-07 22:52       ` Chad R. Meiners
@ 2003-10-08  9:20         ` Duncan Sands
  2003-10-08 16:16           ` C array to Ada pointer to unconstrained array withoutcopyingmemory Chad R. Meiners
  0 siblings, 1 reply; 28+ messages in thread
From: Duncan Sands @ 2003-10-08  9:20 UTC (permalink / raw)
  To: Chad R. Meiners, comp.lang.ada

On Wednesday 08 October 2003 00:52, Chad R. Meiners wrote:
> "Chad R. Meiners" <crmeiners@hotmail.com> wrote in message
> news:blvfo6$q6s$1@msunews.cl.msu.edu...
>
> > declare
> >     C_Data_Ptr       :  Systems.Address := To_Address(My_C_Ptr);
> >     C_Data_Length :  Natural   := ...;
> >
> >     type My_Ada_Type_Element is ...;
> >     type My_Ada_Array is array(Natural range <>) of My_Ada_Type_Element;
> >
> >     subtype My_C_Data_As_An_Ada_Array_Type is
> > My_Ada_Array(1..C_Data_Length);
> >     package My_Converter is new
> > Address_To_Access_Conversions(My_C_Data_As_An_Ada_Array_Type);
> >     C_Data_In_Ada : My_Ada_Array renames
> > My_Converter.To_Pointer(C_Data_Ptr).all;
> >     -- No copying of the array done, but the array dope that you want is
> > built from the subtype information.
> > begin
> > ...
> > end;
>
> I should probably add that you can just get the pointer with
>
> My_Ada_Array_Ptr : My_Converter.Object_Pointer :=
> My_Converter.To_Pointer(C_Data_Ptr);
>
> I believe that this satisfies your needs?

Not in the slightest.  Once you leave this local block, the pointer is
unusable because the array dope, stored as a local variable of the
block, will disappear.  The data continues to hang around of course.

Thanks anyway,

Duncan.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-08  2:14     ` C array to Ada pointer to unconstrained array without copying memory Robert I. Eachus
@ 2003-10-08  9:27       ` Duncan Sands
  2003-10-08 22:43         ` Robert I. Eachus
  0 siblings, 1 reply; 28+ messages in thread
From: Duncan Sands @ 2003-10-08  9:27 UTC (permalink / raw)
  To: Robert I. Eachus, comp.lang.ada

On Wednesday 08 October 2003 04:14, Robert I. Eachus wrote:
> Duncan Sands wrote:
> > So far so good.  Now suppose I do:
> >
> > Y : Array_Pointer := new Array_Type' (X);  -- (*)
> >
> > The object I want is Y.  What is the problem?  The problem
> > is that line (*) involves allocating memory and copying the
> > data from X to that memory.  I would like to end up with Y
> > without performing the copy (and without reallocating
> > memory for the array data).
>
> What is wrong with:
>
> Y: Array_Type;
> for Y'Address use X'Address;
>
> ..if you want X and Y to be two different views of the same memory.
> Notice that there is no need for an explicit pointer here, but if X is a
>   pointer as in your example, you may want to do:
>
> Y: Array_Type;
> for Y'Address use X.all'Address;
>
> Oh, and if there is initialization for the elements of Array_Type you
> may want to add a pragma Import; to turn off initialization.

Hi Robert, maybe I can explain it like this.  The data I have is on
the heap.  I want the array bounds on the heap as well.  In the
solution you suggest, the bounds of the variable Y will in general
be allocated on the stack (Y is declared in a local block), not on
the heap.  A fat pointer pointing to the array will have one part
pointing to the data (which is on the heap and obtained from C)
and the other part pointing to the dope (= bounds, and on the
stack).  At least this is how GNAT does it (which is all I care
about).  Once you leave the local block, the fat pointer can no
longer be used because the stack has been wound up and the
bounds are gone.  However, if the bounds were on the heap too,
it would be a different story.

Ciao,

Duncan.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-07 14:43 C array to Ada pointer to unconstrained array without copying memory Duncan Sands
                   ` (2 preceding siblings ...)
  2003-10-07 20:53 ` Chad R. Meiners
@ 2003-10-08 14:07 ` Steve Adams
  2003-10-08 14:33   ` Preben Randhol
                     ` (2 more replies)
  3 siblings, 3 replies; 28+ messages in thread
From: Steve Adams @ 2003-10-08 14:07 UTC (permalink / raw)


Duncan,
  I have had to do this for my project. What I do is not portable really but
in general is OK if no other solution is available.

Gnat does indeed use Fat pointers. *By Default*
You can make it use thin pointers though:

type var_arr is array (positive range <>) of T;
type var_arr_ptr is access var_arr;
for var_arr_ptr'size use DWORD; -- from memory, probably want a 'size of int
or something

The var_arr_ptr will only be a standard platform pointer size, 32 bits for
ease in the rest of discussion.
The pointer in *GNAT* points to the data (satisfies LRM that arr'access
points to data) and immediately before this are
the bounds, two ints every case i have for 1D arrays, lower then upper ->

[l bound][u bound][data....]

You need to do some pointer manipulations in C when first allocating them to
set the bounds, but Gnat just treats the arrays as normal.
Gnat is good like this since it means that C pointer is handled the same as
Ada pointer.

ObjectAda however has the access value pointing to the bounds, this gives me
quite a few headaches in my work, but gnat has a problem with the calling
convention I need and doesn't handle discriminants properly with the
convention.

For function calls the array can be passed as:
f( pa : in var_arr_ptr) -- reference, NOTE that it is NOT in out, since that
would be a pointer to a pointer
f( pa : in out var_arr) -- behind the scenes reference passed because of
access parameters.

Usual caveats apply that Gnat might change this scheme, however its unlikly.

For infomration the Fat pointer is a struct with two pointers, one to the
bounds and one to the data. Surprise is that the layout of the bounds and
data in memory is the same, so they are allocated in a single call, this
means thin and fat are the same at the basest level, you just have more
overhead for fats.

before language lawyers attack, my project uses intermixed Ada, Fortran,
C/C++ and Pascal. You end up sacrificing portability if you want it to work,
in C this isn't a problem, a single code base manipulated via the
preprocessor is easy, as does fortran. Ada doesn't which makes life hard. I
wish theyed make preprocessing a feature.

Steve A


"Duncan Sands" <baldrick@free.fr> wrote in message
news:mailman.37.1065537708.25614.comp.lang.ada@ada-france.org...
> Greetings.  Given a C pointer Ptr to a type T (which points to a block of
memory
> containing a C array of T's) and the length of the array Length, there are
various
> tricks for getting an Ada array of the right size (defined on the stack -
important!)
> that uses the block of memory to hold the array data, i.e. no copying
required.
>
> For example,
>
> type Ada_Array is array (Positive range <>) of T;
>
> ...
>
> [have Length and Ptr]
>
> subtype Array2 is Ada_Array (1 .. Length);
>
> X : Array2;
> for X'Address use Ptr; -- ok, Ptr should be of type System'Address, but
hey!
>
> And then you can make use of X.  However being defined on the stack, it
> can be quite awkward to use.  It would be nice to have the same thing but
> with X dynamically allocated.  For example,
>
> type Ada_Array_Pointer is access Ada_Array;
>
> ...
>
> [have Length and Ptr]
>
> X_Ptr : Ada_Array_Pointer;
>
> [do some clever stuff to set up X_Ptr to point to an array where the
> data is given by Ptr, and the bounds are somewhere else, but where? :)]
>
> [Pass X_Ptr around and dereference it etc.]
>
> The problem is the bounds of course.  For example, GNAT usually uses
> fat pointers, consisting of two normal pointers where one points to the
> data, and the other to the bounds.  So the "clever stuff" will need to
> allocate some memory to hold the bounds and set up the fat pointer
> appropriately.
>
> Does anyone know a good way to do this?  The solution only needs to
> work with GNAT.  I appreciate that deallocating the pointer may need
> to be handled specially.
>
> All the best,
>
> Duncan.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-08 14:07 ` Steve Adams
@ 2003-10-08 14:33   ` Preben Randhol
  2003-10-09 23:04     ` Steve Adams
  2003-10-08 16:30   ` Duncan Sands
  2003-10-23 21:27   ` C array to Ada pointer to unconstrained array without copying memory Craig Carey
  2 siblings, 1 reply; 28+ messages in thread
From: Preben Randhol @ 2003-10-08 14:33 UTC (permalink / raw)


On 2003-10-08, Steve Adams <s.adams_s_p_a_m_217@_s_p_a_m_ntlworld.csopam> wrote:
> before language lawyers attack, my project uses intermixed Ada, Fortran,
> C/C++ and Pascal. You end up sacrificing portability if you want it to work,
> in C this isn't a problem, a single code base manipulated via the
> preprocessor is easy, as does fortran. Ada doesn't which makes life hard. I
> wish theyed make preprocessing a feature.

Use packages/child packages.

Preprocessing is a bad idea. IMHO The code becomes messy.

By the way what are you doing that need so much OS spesific code?

Preben



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array withoutcopyingmemory
  2003-10-08  9:20         ` Duncan Sands
@ 2003-10-08 16:16           ` Chad R. Meiners
  2003-10-08 16:49             ` Duncan Sands
  0 siblings, 1 reply; 28+ messages in thread
From: Chad R. Meiners @ 2003-10-08 16:16 UTC (permalink / raw)



"Duncan Sands" <duncan.sands@math.u-psud.fr> wrote in message
news:mailman.49.1065604749.25614.comp.lang.ada@ada-france.org...
> On Wednesday 08 October 2003 00:52, Chad R. Meiners wrote:
> > "Chad R. Meiners" <crmeiners@hotmail.com> wrote in message
> > news:blvfo6$q6s$1@msunews.cl.msu.edu...
> >
> > > declare
> > >     C_Data_Ptr       :  Systems.Address := To_Address(My_C_Ptr);
> > >     C_Data_Length :  Natural   := ...;
> > >
> > >     type My_Ada_Type_Element is ...;
> > >     type My_Ada_Array is array(Natural range <>) of
My_Ada_Type_Element;
> > >
> > >     subtype My_C_Data_As_An_Ada_Array_Type is
> > > My_Ada_Array(1..C_Data_Length);
> > >     package My_Converter is new
> > > Address_To_Access_Conversions(My_C_Data_As_An_Ada_Array_Type);
> > >     C_Data_In_Ada : My_Ada_Array renames
> > > My_Converter.To_Pointer(C_Data_Ptr).all;
> > >     -- No copying of the array done, but the array dope that you want
is
> > > built from the subtype information.
> > > begin
> > > ...
> > > end;
> >
> > I should probably add that you can just get the pointer with
> >
> > My_Ada_Array_Ptr : My_Converter.Object_Pointer :=
> > My_Converter.To_Pointer(C_Data_Ptr);
> >
> > I believe that this satisfies your needs?
>
> Not in the slightest.  Once you leave this local block, the pointer is
> unusable because the array dope, stored as a local variable of the
> block, will disappear.  The data continues to hang around of course.

So do the declare at the library level.

-CRM.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-08 14:07 ` Steve Adams
  2003-10-08 14:33   ` Preben Randhol
@ 2003-10-08 16:30   ` Duncan Sands
  2003-10-09 22:59     ` C array to Ada pointer to unconstrained array without copyingmemory Steve Adams
  2003-10-23 21:27   ` C array to Ada pointer to unconstrained array without copying memory Craig Carey
  2 siblings, 1 reply; 28+ messages in thread
From: Duncan Sands @ 2003-10-08 16:30 UTC (permalink / raw)
  To: Steve Adams, comp.lang.ada

Hi Steve, thanks for the interesting information.

> For infomration the Fat pointer is a struct with two pointers, one to the
> bounds and one to the data. Surprise is that the layout of the bounds and
> data in memory is the same, so they are allocated in a single call, this
> means thin and fat are the same at the basest level, you just have more
> overhead for fats.

Do you mean that the bounds are also stored directly before the data in
memory?  If so, it should still be possible to have the two pointers point
to quite different memory areas - after all, when you use an address clause
to say that the data is somewhere, the bounds will be on the stack and thus
not immediately before the data.  Does this mean that if you free a fat
pointer using Unchecked_Deallocation, then only the memory pointed to by
the bounds part is freed?  (Because the memory is allocated as one block,
the bounds point to the start, the data a bit further along).

Thanks again for your help - I'm glad someone understood my question.

All the best,

Duncan.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array withoutcopyingmemory
  2003-10-08 16:16           ` C array to Ada pointer to unconstrained array withoutcopyingmemory Chad R. Meiners
@ 2003-10-08 16:49             ` Duncan Sands
  0 siblings, 0 replies; 28+ messages in thread
From: Duncan Sands @ 2003-10-08 16:49 UTC (permalink / raw)
  To: Chad R. Meiners, comp.lang.ada

> So do the declare at the library level.

That means you have to get the data from C at the same level.
That is not in general possible.

Duncan.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-08  9:27       ` Duncan Sands
@ 2003-10-08 22:43         ` Robert I. Eachus
  2003-10-09  9:31           ` Duncan Sands
  0 siblings, 1 reply; 28+ messages in thread
From: Robert I. Eachus @ 2003-10-08 22:43 UTC (permalink / raw)


Duncan Sands wrote:
> On Wednesday 08 October 2003 04:14, Robert I. Eachus wrote:
> 
>>Duncan Sands wrote:
>>
>>>So far so good.  Now suppose I do:
>>>
>>>Y : Array_Pointer := new Array_Type' (X);  -- (*)
>>>
>>>The object I want is Y.  What is the problem?  The problem
>>>is that line (*) involves allocating memory and copying the
>>>data from X to that memory.  I would like to end up with Y
>>>without performing the copy (and without reallocating
>>>memory for the array data).
>>
>>What is wrong with:
>>
>>Y: Array_Type;
>>for Y'Address use X'Address;
>>
>>..if you want X and Y to be two different views of the same memory.
>>Notice that there is no need for an explicit pointer here, but if X is a
>>  pointer as in your example, you may want to do:
>>
>>Y: Array_Type;
>>for Y'Address use X.all'Address;
>>
>>Oh, and if there is initialization for the elements of Array_Type you
>>may want to add a pragma Import; to turn off initialization.
> 
> 
> Hi Robert, maybe I can explain it like this.  The data I have is on
> the heap.  I want the array bounds on the heap as well.

Then put them there!  I'll leave the details to you, since you know what 
you are trying to do.  But I'll explain what you seem to want.

You have an object, in C, that you "know" the bounds of.  You want to 
write a procedure that can accept a (C) pointer to the data on the heap, 
and construct an Ada object that you can work with.  You also don't seem 
to want to move the data.  (If you are willing to do so, this all gets a 
lot easier.)

Now define an Ada record type, probably in a (library) package spec, 
since you want to be able to pass objects of the type around.  The 
package will be implementing what is referred to as an abstract data 
type.  You can make the type private and put the implementation details 
in the private part of the spec, or even in the body if you really want 
to.  But easiest is to let other units see the implementation at first.

The record type will contain the bounds, and a pointer to the data.  For 
example:

     type Some_Data is record
        First, Last: Integer;
        Data: Some_Pointer;
        -- may be from an instantiation of Interfaces.C.Pointers.
     end record;

Now add your own access type:

    type My_Pointer is access Some_Data;

Next go off and write all the code that passes objects of type Some_Data 
around.  As you do so, you may want to "reach into" your data.  Resist 
the temptation, and write inquiry functions such as:

    function First_Element(P: My_Pointer) return Data_Element;

and put them in your package body.  You probably also want a create 
function that calls the C routine, creates an object on the heap, and 
returns a pointer.  (Notice that the data is also on the heap but it 
doesn't get moved around.  The object you create only contains the bounds.)

It sounds like a lot of work, and it will be for you at first.  But when 
you get used to it, this is a very useful design pattern in Ada.  Of 
course, if you didn't insist on putting the data on the heap, you could 
just pass objects of type Some_Data around.  In Ada you will soon find 
that this is easier than creating access types all over the place.


-- 
                                    Robert I. Eachus

"Quality is the Buddha. Quality is scientific reality. Quality is the 
goal of Art. It remains to work these concepts into a practical, 
down-to-earth context, and for this there is nothing more practical or 
down-to-earth than what I have been talking about all along...the repair 
of an old motorcycle."  -- from Zen and the Art of Motorcycle 
Maintenance by Robert Pirsig




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-08 22:43         ` Robert I. Eachus
@ 2003-10-09  9:31           ` Duncan Sands
  0 siblings, 0 replies; 28+ messages in thread
From: Duncan Sands @ 2003-10-09  9:31 UTC (permalink / raw)
  To: Robert I. Eachus, comp.lang.ada

> > Hi Robert, maybe I can explain it like this.  The data I have is on
> > the heap.  I want the array bounds on the heap as well.
>
> Then put them there!  I'll leave the details to you, since you know what
> you are trying to do.  But I'll explain what you seem to want.
>
> You have an object, in C, that you "know" the bounds of.  You want to
> write a procedure that can accept a (C) pointer to the data on the heap,
> and construct an Ada object that you can work with.  You also don't seem
> to want to move the data.  (If you are willing to do so, this all gets a
> lot easier.)
>
> Now define an Ada record type, probably in a (library) package spec,
> since you want to be able to pass objects of the type around.  The
> package will be implementing what is referred to as an abstract data
> type.  You can make the type private and put the implementation details
> in the private part of the spec, or even in the body if you really want
> to.  But easiest is to let other units see the implementation at first.

Hi Robert, thanks for your help.  Don't worry - I know all about abstract
data types.  I've been using Ada for many years now :)  I was asking
a specific GNAT dependant technical question, simply because I would
like to know (for my own satisfaction) if I can create a true unconstrained
Ada array on the heap from C data without copying.  There is such a
thing as intellectual curiosity!

All the best,

Duncan. 

> The record type will contain the bounds, and a pointer to the data.  For
> example:
>
>      type Some_Data is record
>         First, Last: Integer;
>         Data: Some_Pointer;
>         -- may be from an instantiation of Interfaces.C.Pointers.
>      end record;
>
> Now add your own access type:
>
>     type My_Pointer is access Some_Data;
>
> Next go off and write all the code that passes objects of type Some_Data
> around.  As you do so, you may want to "reach into" your data.  Resist
> the temptation, and write inquiry functions such as:
>
>     function First_Element(P: My_Pointer) return Data_Element;
>
> and put them in your package body.  You probably also want a create
> function that calls the C routine, creates an object on the heap, and
> returns a pointer.  (Notice that the data is also on the heap but it
> doesn't get moved around.  The object you create only contains the bounds.)
>
> It sounds like a lot of work, and it will be for you at first.  But when
> you get used to it, this is a very useful design pattern in Ada.  Of
> course, if you didn't insist on putting the data on the heap, you could
> just pass objects of type Some_Data around.  In Ada you will soon find
> that this is easier than creating access types all over the place.



^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copyingmemory
  2003-10-08 16:30   ` Duncan Sands
@ 2003-10-09 22:59     ` Steve Adams
  2003-10-10  7:02       ` Duncan Sands
  0 siblings, 1 reply; 28+ messages in thread
From: Steve Adams @ 2003-10-09 22:59 UTC (permalink / raw)


Not sure, let me answer a different question :)

Fat pointer is, and forgive me for using C, but otherwise ada would need
type definitions for lots of things

typedef struct
{
    int *bounds;
    T *data;
} Fat_Pointer;

Then when you declare:

fp : Fat_Pointer := NULL;

it means that the pointers are actually null, the fp variable is the size of
the structure above, 2 32 bit values for ease.

when you do:

fp := new t(1..20);

then what happens in essence is:

allocate enough memory for 20*sizeof(T) + 2 * sizeof(int) (for bounds)

fp.bounds = 20*sizeof(T) + 2 * sizeof(int)
fp.bounds(1) := 1;
fp.bounds(2) := 20;
fp.data = (T*)(fp.bounds+2); -- O/S conversion, but basically move 2 int
sizes along in memory

When you deallocate you release the memory pointed to.

To take this to the C - Ada chat level, and using a thin pointer because of
'size applied:

void cf()
{
    int *data;
    data = malloc((N_ELEMENTS + 2)*sizeof(int);
    data[0] = 1;
    data[1] = N_ELEMENTS;
    data += 2;
    for (i =0; i < N_ELEMENTS; i++)
    {
        data[i] = i;
    }
    ada_func(data, data);
}

------
procedure ada_func(p_ia_1 : int_arr_ptr; p_ia_2 : in out int_arr) is
begin
    for i in p_ia_1'first .. p_ia_1'last loop
        text_io.put_line("p_ia_1 (" & integer'image(i) & "} = " &
integer'image(p_ia_1(i)) );
   end loop;
end ada_func;

I actually have code that does this and works (well something more useful
anway).

Objectada uses thin pointers by default. btw.

Freeing a fat pointer with unchecked_deallocation is a good question, I
would guess that it does free correctly. However its any ones guess outside
of Gnat whether the data is freed in one call or as two. If two I am in
trouble :)
However, every time i traced the use of these things the bounds were ALWAYS
immediately before the data in memory, suggesting a single allocation from
the heap.
If you use a thin pointer then I'd be pretty sure that you will always have
correct behavour as by definition the bounds must reside at the start of the
data in someway.


"Duncan Sands" <duncan.sands@math.u-psud.fr> wrote in message
news:mailman.51.1065630515.25614.comp.lang.ada@ada-france.org...
> Hi Steve, thanks for the interesting information.
>
> > For infomration the Fat pointer is a struct with two pointers, one to
the
> > bounds and one to the data. Surprise is that the layout of the bounds
and
> > data in memory is the same, so they are allocated in a single call, this
> > means thin and fat are the same at the basest level, you just have more
> > overhead for fats.
>
> Do you mean that the bounds are also stored directly before the data in
> memory?  If so, it should still be possible to have the two pointers point
> to quite different memory areas - after all, when you use an address
clause
> to say that the data is somewhere, the bounds will be on the stack and
thus
> not immediately before the data.  Does this mean that if you free a fat
> pointer using Unchecked_Deallocation, then only the memory pointed to by
> the bounds part is freed?  (Because the memory is allocated as one block,
> the bounds point to the start, the data a bit further along).
>
> Thanks again for your help - I'm glad someone understood my question.
>
> All the best,
>
> Duncan.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-08 14:33   ` Preben Randhol
@ 2003-10-09 23:04     ` Steve Adams
  2003-10-09 23:11       ` Steve Adams
  0 siblings, 1 reply; 28+ messages in thread
From: Steve Adams @ 2003-10-09 23:04 UTC (permalink / raw)


It's a plug in architectured simulation system. Used to live on VMS, but
moving it to windows and linux, possibly other OS if needed.
Trying to allow developers to use whatever tool they like to develop, I have
working example plug ins in C, C++, Ada, Pascal, Fortran, Visual Basic.
So different compilers are using the same interfaces (there's about 500
structures), but also a need to change layouts sometimes depending on OS.

Plus DLL creation from ObjectAda and Gnat is different, DLL main is needed
for Gnat for library initialisation, but OA does it for me, so I have to
comment out packages by hand.

We needed OA for the Codeview debug information at first, since the legacy
elements needed to be checked, and the main core is VC++. However, we are
trying to remain syntacticaly compatible with Gnat for future versions when
the discrimiant check works on the DLL calling convention. I have an example
that I might post to the newsgroup if I ever get time.

BTW thanks to anyone that chatted about controlled types in Ada95, they were
a life saver!

"Preben Randhol" <randhol+valid_for_reply_from_news@pvv.org> wrote in
message
news:slrnbo8819.4fb.randhol+valid_for_reply_from_news@kiuk0152.chembio.ntnu.no...
> On 2003-10-08, Steve Adams <s.adams_s_p_a_m_217@_s_p_a_m_ntlworld.csopam>
wrote:
> > before language lawyers attack, my project uses intermixed Ada, Fortran,
> > C/C++ and Pascal. You end up sacrificing portability if you want it to
work,
> > in C this isn't a problem, a single code base manipulated via the
> > preprocessor is easy, as does fortran. Ada doesn't which makes life
hard. I
> > wish theyed make preprocessing a feature.
>
> Use packages/child packages.
>
> Preprocessing is a bad idea. IMHO The code becomes messy.
>
> By the way what are you doing that need so much OS spesific code?
>
> Preben





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-09 23:04     ` Steve Adams
@ 2003-10-09 23:11       ` Steve Adams
  0 siblings, 0 replies; 28+ messages in thread
From: Steve Adams @ 2003-10-09 23:11 UTC (permalink / raw)


Oh, sorry about top posting, used to our internal newsgroups in work, where
its a lot faster.

<SNIP>





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copyingmemory
  2003-10-09 22:59     ` C array to Ada pointer to unconstrained array without copyingmemory Steve Adams
@ 2003-10-10  7:02       ` Duncan Sands
  2003-10-10 16:44         ` C array to Ada pointer to unconstrained array withoutcopyingmemory Steve Adams
  0 siblings, 1 reply; 28+ messages in thread
From: Duncan Sands @ 2003-10-10  7:02 UTC (permalink / raw)
  To: Steve Adams, comp.lang.ada

> Freeing a fat pointer with unchecked_deallocation is a good question, I
> would guess that it does free correctly. However its any ones guess outside
> of Gnat whether the data is freed in one call or as two. If two I am in
> trouble :)
>
> However, every time i traced the use of these things the bounds were ALWAYS
> immediately before the data in memory, suggesting a single allocation from
> the heap.

Yes, it seems like an obvious optimization: arrays allocated on the heap can have
no address clause, so you can put the bounds with the data if you like, and reduce
the number of memory allocations.  Also, if the bounds are immediately before the
data, doesn't that prove that it was done in one memory allocation, since (IIRC)
malloc reserves some bytes for itself just before a block of memory it allocates, and
GNAT uses malloc?

Ciao,

Duncan.




^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array withoutcopyingmemory
  2003-10-10  7:02       ` Duncan Sands
@ 2003-10-10 16:44         ` Steve Adams
  0 siblings, 0 replies; 28+ messages in thread
From: Steve Adams @ 2003-10-10 16:44 UTC (permalink / raw)


"Duncan Sands" <baldrick@free.fr> wrote in message
news:mailman.57.1065769242.25614.comp.lang.ada@ada-france.org...
> > Freeing a fat pointer with unchecked_deallocation is a good question, I
> > would guess that it does free correctly. However its any ones guess
outside
> > of Gnat whether the data is freed in one call or as two. If two I am in
> > trouble :)
> >
> > However, every time i traced the use of these things the bounds were
ALWAYS
> > immediately before the data in memory, suggesting a single allocation
from
> > the heap.
>
> Yes, it seems like an obvious optimization: arrays allocated on the heap
can have
> no address clause, so you can put the bounds with the data if you like,
and reduce
> the number of memory allocations.  Also, if the bounds are immediately
before the
> data, doesn't that prove that it was done in one memory allocation, since
(IIRC)
> malloc reserves some bytes for itself just before a block of memory it
allocates, and
> GNAT uses malloc?
>
> Ciao,
>
> Duncan.
>

As you say, it makes sense to allocate the bounds & data in a single call,
I'm not sure if it also fits that 'access for an unbounded array type is
supposed to return a reference to the first element, this might be a Gnatism
rather than an LRM statement.

Good luck on the use of this, if you find out how Gnat lays out the bounds
for a 2D array, please let me know, it might be a useful piece of knowledge,
my guess is that it will be

[x low bound][x up bound][y low bound][y up bound]

As that keeps making sense no matter how far you scale it for dimensions.
Bear in mind that Gnat may change the layout of these things, so it's worth
writing a piece of test code to print memory around unbound arrays in C that
you can call. Then should Gnat release a new version, you can run this and
feel happy that the memory layout is still the same.

A really quick example of this might be:

-- Ada
procedure check_d_a is
type i_arr is array (positive range <>) of integer;
type i_arr_ptr_thin is access i_arr;
for i_arr_ptr_thin'size use 32; -- machine dependant

procedure C_Mem(the_array : in out i_arr_ptr_thin; lbound, ubound :
integer);
pragma import(C,C_Mem, "_c_mem"); -- need to look at your linker

    ia : i_arr_ptr_thin := NULL;

begin
    ia := new i_arr(99..101); -- easy to look for values
    for i in ia'first .. ia'last loop
        ia(i) := i-99+2002; -- again, easy to look for values, consider
using hex, that way you can look for easy 'strings'
    end loop;
    c_mem(ia,ia'fist,ia'last);

end check_d_a;

// C
#define MEM_OFFSET 20
extern "C" void c_mem(int *arr,int l, int h)
{
    printf("BOUNDS: %d .. %d\n",l,h);
    int sz = (h - l)+1;
    int *cparr = arr - MEM_OFFSET; // work 20 ints before data
    for(int i=0; i < sz + MEM_OFFSET; i++)
    {
        printf("OFFSET:%d\tMEM location
0x%08X\tVAL%d\n",i-MEM_OFFSET,cparr,*cparr);
        cparr++;
    }
}

All written without checking, so there will be a bug or two.
You should then see something like:
OFFSET:-20       Mem location:0xE0F00FF0A1   VAL:-848484776
..
OFFSET:-2         Mem Location:0xE0F00F1F3    VAL:99
OFFSET:-1         Mem Location:0xE0F00F1F4    VAL:101
OFFSET:0         Mem Location:0xE0F00F1F5    VAL:2002







^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-08 14:07 ` Steve Adams
  2003-10-08 14:33   ` Preben Randhol
  2003-10-08 16:30   ` Duncan Sands
@ 2003-10-23 21:27   ` Craig Carey
  2 siblings, 0 replies; 28+ messages in thread
From: Craig Carey @ 2003-10-23 21:27 UTC (permalink / raw)


On Wed, 8 Oct 2003 15:07:48 +0100, "Steve Adams"
<s.adams_s_p_a_m_217@_s_p_a_m_ntlworld.csopam> wrote:

>Duncan,
>  I have had to do this for my project. What I do is not portable really but
>in general is OK if no other solution is available.
>
>Gnat does indeed use Fat pointers. *By Default*.
>You can make it use thin pointers though:
>
>type var_arr is array (positive range <>) of T;
>type var_arr_ptr is access var_arr;
>for var_arr_ptr'size use DWORD; -- from memory, probably want a 'size of int
>  or something
...

>You need to do some pointer manipulations in C when first allocating them to
>set the bounds, but Gnat just treats the arrays as normal.
>Gnat is good like this since it means that C pointer is handled the same as
>Ada pointer.
...
>ObjectAda however has the access value pointing to the bounds, this gives me
>quite a few headaches in my work, but gnat has a problem with the calling
...

>For information the Fat pointer is a struct with two pointers, one to the
>bounds and one to the data.
...

Taking the bounds information off is needed for interfacing with C.

(It is done by declaring what the exact size of the array is. Then the
double pointer becomes the single pointer C code would expect.)

----
   package IC renames Interfaces.C;

   type C_Array is array (Natural range <>) of XYZ;
   subtype Big_C_Array is C_Array (0 .. Natural'Last);  -- Thin pointer
                             --    0 .. 2,147,483,647
   type Big_C_Array_Ptr is access all Big_C_Array;

   pragma Convention (Convention => C, Entity => C_Array);

   procedure C_Ada_Proc (W : Big_C_Array_Ptr; Len : IC.int);
   pragma Export (C, C_Proc); 
...

   procedure C_Ada_Proc (W : Big_C_Array_Ptr; Len : IC.int)
   is
      type A_W is array (1 .. Len) of IC.int;
      type A_W_Ptr is access all A_W;

      function UC_W is new Ada.Unchecked_Conversion (
                        Source => Big_C_Array_Ptr, Target => A_W_Ptr);

      ZW1         : A_W_Ptr := UC_W (W);   --  points to 1st element

      CA          : A_W renames ZW1.all;   --  The same array C sees


Mr Sands question might have been answered better if the code causing
the problem was shown. C code won't lead to a need to know about the
internal design of an Ada compiler. Actually producing the C code might
indicate that somehow. Also perhaps Mr Sands could create the bounds
info instead of GNAT.


>"Duncan Sands"  wrote in message
>news:mailman.37.1065537708.25614.comp.lang.ada@ada-france.org...
>> Greetings.  Given a C pointer Ptr to a type T (which points to a block of
>>memory containing a C array of T's) and the length of the array Length,
>> there are various tricks for getting an Ada array of the right size
>> (defined on the stack - important!)
>> that uses the block of memory to hold the array data, i.e. no copying
>required.
>>
>> For example,
>>
>> type Ada_Array is array (Positive range <>) of T;
...
>> The problem is the bounds of course.  For example, GNAT usually uses
>> fat pointers, consisting of two normal pointers where one points to the
...





^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2003-10-23 21:27 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-07 14:43 C array to Ada pointer to unconstrained array without copying memory Duncan Sands
2003-10-07 18:30 ` tmoran
2003-10-07 19:24   ` Duncan Sands
2003-10-08  0:02   ` sk
     [not found]   ` <3F83540E.5000302@myob.com>
2003-10-08  9:18     ` Duncan Sands
2003-10-07 20:00 ` Jeffrey Carter
2003-10-07 20:39   ` Duncan Sands
2003-10-08  1:27     ` Jeffrey Carter
2003-10-07 20:53 ` Chad R. Meiners
2003-10-07 21:24   ` Duncan Sands
2003-10-07 22:44     ` C array to Ada pointer to unconstrained array without copyingmemory Chad R. Meiners
2003-10-07 22:52       ` Chad R. Meiners
2003-10-08  9:20         ` Duncan Sands
2003-10-08 16:16           ` C array to Ada pointer to unconstrained array withoutcopyingmemory Chad R. Meiners
2003-10-08 16:49             ` Duncan Sands
2003-10-08  2:14     ` C array to Ada pointer to unconstrained array without copying memory Robert I. Eachus
2003-10-08  9:27       ` Duncan Sands
2003-10-08 22:43         ` Robert I. Eachus
2003-10-09  9:31           ` Duncan Sands
2003-10-08 14:07 ` Steve Adams
2003-10-08 14:33   ` Preben Randhol
2003-10-09 23:04     ` Steve Adams
2003-10-09 23:11       ` Steve Adams
2003-10-08 16:30   ` Duncan Sands
2003-10-09 22:59     ` C array to Ada pointer to unconstrained array without copyingmemory Steve Adams
2003-10-10  7:02       ` Duncan Sands
2003-10-10 16:44         ` C array to Ada pointer to unconstrained array withoutcopyingmemory Steve Adams
2003-10-23 21:27   ` C array to Ada pointer to unconstrained array without copying memory Craig Carey

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