comp.lang.ada
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* Re: Messing with access types...
  2020-12-28 11:43  5%   ` Marek
@ 2020-12-28 13:56  0%     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 144+ results
From: Dmitry A. Kazakov @ 2020-12-28 13:56 UTC (permalink / raw)


On 2020-12-28 12:43, Marek wrote:
> On 28.12.2020 11:14, Dmitry A. Kazakov wrote:
>>
>> What are you trying to achieve? Because the code does not make much
>> sense to me.
>>
>> P.S. If you are trying to do some C bindings flat arrays are easier
>> choice than Interfaces.C.Pointers. C has no arrays, but pointers. Ada's
>> arrays are never compatible with any pointers, except when flat.
>> Therefore using access to String would be wrong in most, if not all, cases.
> 
> Code is a fragment some plugin framework for host written in C. When
> plugin is initialized it receives pointer to host features. Then I can
> scan them to find concrete feature (Id) and retrieve data.
> Problem is with instantiation generic function Get_Data, more precisely
> in line:
> 
>     return T_Access (ATA.To_Pointer (F.Data));

You should never convert access types, because to do so, you must first 
learn the accessibility rules. No man can do that while keeping sanity. 
So, just do this:

    return ATA.To_Pointer (F.Data).all'Unchecked_Access;
        -- Mind your business, COMPILER!

> OK, some changes to code to clear view:
> 
> with System;
> 
> package Util is
> 
>     type Feature is record
>        Id  : Integer;
>        Data : System.Address;
>     end record;

    type Feature is record
       Id   : Interfaces.C.int; -- If that is int
       Data : System.Address;   -- Could be a named access type [*]
    end record;
    pragma Convention (C, Feature);

>     type Feature_Access is access all Feature;
> 
>     Null_Feature : constant Feature := (0, System.Null_Address);


>     type Feature_Array is array (Natural range <>) of aliased Feature;

    type Feature_Array is array (size_t) of aliased Feature; -- Flat
    pragma Convention (C, Feature_Array);
    type Feature_Array_Ptr is access all Feature_Array;
    pragma Convention (C, Feature_Array_Ptr);

    function Get_Me_Features return Feature_Array_Ptr;
    pragma Import (C, Get_Me_features, "???");

That should be all necessary to do this:

    List : Feature_Array renames Get_Me_Features.all;
begin
    for I in size_t'Range loop
       exit when List (I) = Null_Feature;
       declare
          Data : Whatever_C_Type;
          for Data'Address use List (I).Data;
          pragma Import (Ada, Data);
       begin
          ...
       end;
    end loop;

-------------------------------------
* Here is a variant without using addresses

    type Whatever_C_Type is record
       ...
    end record;
    pragma Convention (C, Whatever_C_Type);
    type Whatever_C_Type_Ptr is access all Whatever_C_Type;
    pragma Convention (C, Whatever_C_Type_Ptr);

    type Feature is record
       Id   : Interfaces.C.int;
       Data : Whatever_Ptr;
    end record;
    pragma Convention (C, Feature);
    ...

    for I in size_t'Range loop
       exit when List (I) = Null_Feature;
       declare
          Data : Whatever_C_Type renames List (I).Data.all;
       begin
          ...
       end;
    end loop;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[relevance 0%]

* Re: Messing with access types...
  2020-12-28 10:14  6% ` Dmitry A. Kazakov
@ 2020-12-28 11:43  5%   ` Marek
  2020-12-28 13:56  0%     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 144+ results
From: Marek @ 2020-12-28 11:43 UTC (permalink / raw)


On 28.12.2020 11:14, Dmitry A. Kazakov wrote:
> 
> What are you trying to achieve? Because the code does not make much
> sense to me.
> 
> P.S. If you are trying to do some C bindings flat arrays are easier
> choice than Interfaces.C.Pointers. C has no arrays, but pointers. Ada's
> arrays are never compatible with any pointers, except when flat.
> Therefore using access to String would be wrong in most, if not all, cases.
> 

Code is a fragment some plugin framework for host written in C. When
plugin is initialized it receives pointer to host features. Then I can
scan them to find concrete feature (Id) and retrieve data.
Problem is with instantiation generic function Get_Data, more precisely
in line:

   return T_Access (ATA.To_Pointer (F.Data));

OK, some changes to code to clear view:

with System;

package Util is

   type Feature is record
      Id  : Integer;
      Data : System.Address;
   end record;

   type Feature_Access is access all Feature;

   Null_Feature : constant Feature := (0, System.Null_Address);

   type Feature_Array is array (Natural range <>) of aliased Feature;

   generic
      type T is private;
      type T_Access is access all T;
   function Get_Data (H : access Feature; Id : Integer) return T_Access;

   generic
      type T is private;
      type T_Access is access all T;
   function Get_Query
     (H        : access Feature; Id : Integer; Data : in out T_Access;
      Required : Boolean) return Integer;

end Util;

------------------------

pragma Ada_2012;

with Interfaces.C.Pointers;

with System.Address_To_Access_Conversions;

package body Util is

   package Ptr is new Interfaces.C.Pointers
     (Index              => Natural,
      Element            => Feature,
      Element_Array      => Feature_Array,
      Default_Terminator => Null_Feature);

   use Ptr;

   --------------
   -- Get_Data --
   --------------

   function Get_Data (H : access Feature; Id : Integer) return T_Access
   is
      Pointer : Ptr.Pointer := Ptr.Pointer (H);

      package ATA is new System.Address_To_Access_Conversions (T);

   begin
      if H /= null then
         loop
            declare
               F : access Feature := Pointer;
            begin
               if Id = F.Id then
                  return T_Access (ATA.To_Pointer (F.Data));
               end if;
            end;

            Ptr.Increment (Pointer);

            exit when Pointer = null;

         end loop;
      end if;

      return null;
   end Get_Data;

   ---------------
   -- Get_Query --
   ---------------

   function Get_Query
     (H        : access Feature; Id : Integer; Data : in out T_Access;
      Required : Boolean) return Integer
   is
      function Get is new Get_Data (T, T_Access);
   begin

      Data := Get (H, Id);

      if Required and (Data /= null) then
         return Id;
      end if;

      return 0;
   end Get_Query;

end Util;

^ permalink raw reply	[relevance 5%]

* Re: Messing with access types...
  2020-12-28  9:44  4% Messing with access types Marek
@ 2020-12-28 10:14  6% ` Dmitry A. Kazakov
  2020-12-28 11:43  5%   ` Marek
  0 siblings, 1 reply; 144+ results
From: Dmitry A. Kazakov @ 2020-12-28 10:14 UTC (permalink / raw)


On 2020-12-28 10:44, Marek wrote:

> I have some code:

[...]

> When I try to compile test.adb I get some warnings:
> 
> Compile
>     [Ada]          test.adb
> test.adb:20:04: warning: in instantiation at util.adb:34
> test.adb:20:04: warning: in instantiation at util.adb:56
> test.adb:20:04: warning: accessibility check failure
> test.adb:20:04: warning: "Program_Error" will be raised at run time
> test.adb:20:04: warning: in instantiation at util.adb:34
> test.adb:20:04: warning: in instantiation at util.adb:56
> test.adb:20:04: warning: cannot convert local pointer to non-local
> access type
> test.adb:20:04: warning: Program_Error will be raised at run time
>     [Ada]          util.adb
> Bind
>     [gprbind]      test.bexch
>     [Ada]          test.ali
> Link
>     [link]         test.adb
> [2020-12-28 10:30:50] process terminated successfully, elapsed time: 00.92s
> 
> I tried also to move every local (to Test procedure) variables to global
> scope but result is the same.
> 
> What is going on? Can you explain where is the problem?

What are you trying to achieve? Because the code does not make much 
sense to me.

P.S. If you are trying to do some C bindings flat arrays are easier 
choice than Interfaces.C.Pointers. C has no arrays, but pointers. Ada's 
arrays are never compatible with any pointers, except when flat. 
Therefore using access to String would be wrong in most, if not all, cases.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[relevance 6%]

* Messing with access types...
@ 2020-12-28  9:44  4% Marek
  2020-12-28 10:14  6% ` Dmitry A. Kazakov
  0 siblings, 1 reply; 144+ results
From: Marek @ 2020-12-28  9:44 UTC (permalink / raw)


Hello,

I have some code:

- util.ads:

with System;

package Util is

   type Handle is record
      Str  : access String;
      Data : System.Address;
   end record;

   type Handle_Access is access all Handle;

   Null_Handle : constant Handle := (null, System.Null_Address);

   type Handle_Array is array (Natural range <>) of aliased Handle;

   generic
      type T is private;
      type T_Access is access all T;
   function Get_Data (H : access Handle; Str : access String) return
T_Access;

   generic
      type T is private;
      type T_Access is access all T;
   function Get_Query
     (H        : access Handle; Str : access String; Data : in out T_Access;
      Required : Boolean) return access String;

end Util;

- util.adb

pragma Ada_2012;

with Interfaces.C.Pointers;

with System.Address_To_Access_Conversions;

package body Util is

   package Ptr is new Interfaces.C.Pointers
     (Index              => Natural,
      Element            => Handle,
      Element_Array      => Handle_Array,
      Default_Terminator => Null_Handle);

   use Ptr;

   --------------
   -- Get_Data --
   --------------

   function Get_Data (H : access Handle; Str : access String) return
T_Access
   is
      Pointer : Ptr.Pointer := Ptr.Pointer (H);

      package ATA is new System.Address_To_Access_Conversions (T);

   begin
      if H /= null then
         loop
            declare
               F : access Handle := Pointer;
            begin
               if Str.all = F.Str.all then
                  return T_Access (ATA.To_Pointer (F.Data));
               end if;
            end;

            Ptr.Increment (Pointer);

            exit when Pointer = null;

         end loop;
      end if;

      return null;
   end Get_Data;

   ---------------
   -- Get_Query --
   ---------------

   function Get_Query
     (H        : access Handle; Str : access String; Data : in out T_Access;
      Required : Boolean) return access String
   is
      function Get is new Get_Data (T, T_Access);
   begin

      Data := Get (H, Str);

      if Required and (Data /= null) then
         return Str;
      end if;

      return null;
   end Get_Query;

end Util;

- test.adb

pragma Ada_2012;

with Util;

procedure Test is
   use Util;

   type Some_Record is record
      Foo : Integer;
   end record;

   type Some_Record_Access is access all Some_Record;

   Test_Record : Some_Record_Access;

   H : access Handle := null;

   Str : access String := new String'("Test");

   function Query is new Get_Query (Some_Record, Some_Record_Access);

   Result : access String := Query (H, Str, Test_Record, False);
begin
   null;
end Test;

When I try to compile test.adb I get some warnings:

Compile
   [Ada]          test.adb
test.adb:20:04: warning: in instantiation at util.adb:34
test.adb:20:04: warning: in instantiation at util.adb:56
test.adb:20:04: warning: accessibility check failure
test.adb:20:04: warning: "Program_Error" will be raised at run time
test.adb:20:04: warning: in instantiation at util.adb:34
test.adb:20:04: warning: in instantiation at util.adb:56
test.adb:20:04: warning: cannot convert local pointer to non-local
access type
test.adb:20:04: warning: Program_Error will be raised at run time
   [Ada]          util.adb
Bind
   [gprbind]      test.bexch
   [Ada]          test.ali
Link
   [link]         test.adb
[2020-12-28 10:30:50] process terminated successfully, elapsed time: 00.92s

I tried also to move every local (to Test procedure) variables to global
scope but result is the same.

What is going on? Can you explain where is the problem?
thanks in advance

Marek

^ permalink raw reply	[relevance 4%]

* Re: How can one record component be local and another not?
  @ 2020-05-06 19:31  3%       ` hreba
  0 siblings, 0 replies; 144+ results
From: hreba @ 2020-05-06 19:31 UTC (permalink / raw)


On 5/5/20 9:08 PM, Niklas Holsti wrote:
> 
> I don't understand -- System.Address is not an access type; why do you 
> need to use an access type to produce this parameter? Do you need a 
> pointer to the "params" component?
> 
> Perhaps you can show a bit more of the actual code that has the problem?
> 

Ok, I'll try to make it comprehensible without throwing a lot of code at 
you.

I am writing a thick binding to the GSL library odeiv2 for numerically 
integrating ODEs (ordinary differential equations). I already have the 
thin binding gsl_odeiv2_h.ads. For initialization, I have to call the 
following subprogram of the thin binding:

    function gsl_odeiv2_driver_alloc_y_new
      (sys : access constant gsl_odeiv2_system;
       T : access constant gsl_odeiv2_step_type;
       hstart : double;
       epsabs : double;
       epsrel : double) return access gsl_odeiv2_driver;
    pragma Import (C, gsl_odeiv2_driver_alloc_y_new, 
"gsl_odeiv2_driver_alloc_y_new");

Parameter sys defines the ODE; its type is

    type gsl_odeiv2_system is record
       c_function : access function
            (arg1 : double;
             arg2 : access double;
             arg3 : access double;
             arg4 : System.Address) return int;
       jacobian : access function
            (arg1 : double;
             arg2 : access double;
             arg3 : access double;
             arg4 : access double;
             arg5 : System.Address) return int;
       dimension : aliased size_t;
       params : System.Address;
    end record;
    pragma Convention (C_Pass_By_Copy, gsl_odeiv2_system);

Later, during integration, c_function() and jacobian() will be called 
with parameters of type System.Address (arg4 and arg5 resp.). These 
parameters must be passed as params inside sys to 
gsl_odeiv2_driver_alloc_y_new().

Now to my own code (most of the thin binding was created automatically 
with g++ -c -fdump-ada-spec-slim). Dglsys_P corresponds to c_function in 
the thin binding, The package is essentially

generic
    dim:	Positive;
    type Float is digits<>;
package odeiv2 is

      err_noInit,	-- Init_Solve() has not been called
      err_Precision,	-- precision of C.double used in GSL not sufficient
      err_Method,	-- integration method not implemented
      err_SolveAgain:	-- Solve_Again() call without former Solve()
Exception;

    type Float_Array is array (1..dim) of Float;
    type Float_Matrix is array (1..dim, 1..dim) of Float;
    type Par_Array is array (Positive range <>) of Float;
    type Method is (RK8PD);
    type Solver is limited private;

    type Dglsys_P is not null access procedure
      (t:	Float;			-- independent variable
       y:	Float_Array;		-- dependent variables at t
       dydt:	out Float_Array;	-- 1. ordinary derivatives at t
       params:	Par_Array		-- any parameters
      );

    -- omitted: type Jacobi_P is access procedure...

    procedure Init_Solve
      -- Init. a dglsys, must be called once before calling
      -- (once or repeatedly) Solve() or Solve_Again().
      -- The resulting sol must be an access type because of the internal
      -- interface to the GSL library.
      (Dglsys:	Dglsys_P;		-- the system of diff. equ.
       Jacobi:	Jacobi_P;		-- the jacobi calc., if avail.
       pars:	access constant Par_Array;	-- the parameters
       met:	Method;			-- the solve method
       h_start:	Float;			-- initial step size
       epsabs:	Float;			-- absolute error tolerance
       epsrel:	Float;			-- relative error tolerance
       sol:	aliased in out Solver
      );

private

    package C renames Interfaces.C;
    package Ode renames gsl_odeiv2_h;

    type C_Array is array (Integer range <>) of aliased C.double;
    pragma Convention (C, C_Array);

    type Parameters is record
       dglpars:		access constant Par_Array;	-- pars of dglsys
       Dglsys:		Dglsys_P;			-- dglsys calc.
       Jacobi:		Jacobi_P;			-- Jacobi calc.
    end record;
    pragma Convention (C, Parameters);
    type Parameters_Ptr is access all Parameters;

    package Parameters_Conv is new
      System.Address_To_Access_Conversions (Parameters);

    type Solver is limited record
       initialized:	Boolean:= false;	-- Init_Solve() has been called
       firstcall_done:	Boolean;		-- first call done
       store_y:		Boolean;		-- copy y to ya
       ya:		C_Array (1..dim);	-- values of last Solve call
       sys:		aliased Ode.gsl_odeiv2_system;
       driver:		access Ode.gsl_odeiv2_driver;
       all_pars:		aliased Parameters;
       all_pp:		Parameters_Conv.Object_Pointer;
    end record;

end odeiv2;


In the package body I have to define the c_function above (thin binding 
spec.), which will call the corresponding function of type Dglsys_P 
(thick binding), and it finds this in the parameters. then I define the 
initialization subprogram.


package body odeiv2 is

    package C_Arrays is new
      Interfaces.C.Pointers (Integer, C.double, C_Array, 0.0);

    function func (t: C.double; y,f: access C.double; params: 
System.Address)	 return C.int;
    pragma Convention (C, func);

    function func (t: C.double; y,f: access C.double; params: 
System.Address)	 return C.int
      -- GSL version of Dglsys
    is
       use type System.Address;
       all_pars:	Parameters_Conv.Object_Pointer;
       yf, dydt:	Float_Array;
       y0:	C_Arrays.Pointer:= C_Arrays.Pointer(y);
       f0:	C_Arrays.Pointer:= C_Arrays.Pointer(f);
    begin
       all_pars:= Parameters_Conv.To_Pointer (params);
       for i in 1..dim loop
	 yf(i):= Float(y0.all);
	 C_Arrays.Increment (y0);
       end loop;
       all_pars.Dglsys (Float(t), yf, dydt, all_pars.dglpars.all);
       for i in 1..dim loop
	 f0.all:= C.double(dydt(i));
	 C_Arrays.Increment (f0);
       end loop;
       return gsl_errno_h.GSL_SUCCESS;
    end func;


    procedure Init_Solve
      (Dglsys:	Dglsys_P;		-- the system of diff.equ.
       Jacobi:	Jacobi_P;		-- jacobi calc., if available
       pars:	access constant Par_Array;	-- the parameters
       met:	Method;			-- the solve method
       h_start:	Float;			-- initial step size
       epsabs:	Float;			-- absolute error tolerance
       epsrel:	Float;			-- relative error tolerance
       sol:	aliased in out Solver
      )
    is
       gsl_met:	access constant Ode.gsl_odeiv2_step_type;
    begin
       -- set all_pars
       -- sol: flags for calling logic
       sol.Initialized:= true;
       sol.firstcall_done:= false;
       sol.store_y:= true;
       sol.all_pars.dglpars:= pars;
       sol.all_pars.Dglsys:= Dglsys;
       sol.all_pars.Jacobi:= Jacobi;
       -- transform integration method to GSL format
       case met is
	 when RK8PD =>	gsl_met:= Ode.gsl_odeiv2_step_rk8pd;
	 when others =>
	    raise err_Method
	      with "forgot to implement integration method";
       end case;
       -- build sys and driver
       sol.all_pp:= sol.all_pars'Unchecked_Access;
       sol.sys:=
	(func'Access, jac'Access, C.size_t(dim),
	 Parameters_Conv.To_Address (sol.all_pp));
       sol.driver:= Ode.gsl_odeiv2_driver_alloc_y_new
	(sol.sys'Access, gsl_met,
	 C.double(h_start), C.double(epsabs), C.double(epsrel));
       end Init_Solve;

    -- %< -------------
end odeiv2;


The above version compiles. At first I didn't have the Solver component 
all_pp, but passed app_pars'Address to the call of 
gsl_odeiv2_driver_alloc_y_new at the end of Init_Solve. It too compiled.

But whatever I try, I don't get rid of the runtime error

raised CONSTRAINT_ERROR : odeiv2.ads:92:4 access check failed

It accuses the line

    type Parameters is record


-- 
Frank Hrebabetzky, Kronach	+49 / 9261 / 950 0565

^ permalink raw reply	[relevance 3%]

* Re: AdaCore Community 2018 Bugs
  2018-08-12 16:37  6%             ` Simon Wright
  2018-08-13  2:02  4%               ` Roger
@ 2018-08-13  2:54  0%               ` Roger
  1 sibling, 0 replies; 144+ results
From: Roger @ 2018-08-13  2:54 UTC (permalink / raw)


On Monday, August 13, 2018 at 2:37:52 AM UTC+10, Simon Wright wrote:
> Roger <rogermcm2@gmail.com> writes:
> 
> > On Sunday, August 12, 2018 at 5:33:35 PM UTC+10, Simon Wright wrote:
> >> Roger <rogermcm2@gmail.com> writes:
> >> 
> >> > As it now occurs even with GCC 6.1.0 I'm thinking it most likely has
> >> > to do with recent OSX changes.
> >> 
> >> Since it occurs on Debian Stretch, GCC 6.3.0, it can't be just macOS.
> >> 
> >> The actual error reported can change with successive compilations
> >> (sometimes it says something like 'undeclared variable ""', seems to
> >> settle on the CE), a surefire symptom of bad memory handling.
> >> 
> >> > This problem doesn't occur for compile only.
> >> > It occurs when I Build All from GPS
> >> 
> >> The error is a crash in the compiler, doesn't matter how you get there.
> >
> > I Have cut most of the code out of the test program but the crash
> > still occurs.  However, I am making progress on tracking back to the
> > minimal code where the crash first occurs.
> 
> The problem is in the packages Morph.Mesh_Morph_Value_Pointers,
> Mesh_Morph_Weight_Pointers.
> 
> You say
> 
>    package Mesh_Morph_Value_Pointers is new Interfaces.C.Pointers
>      (Interfaces.C.unsigned, API_Morph_Value, API_Morph_Values_Array,
>       API_Morph_Value'(others => <>));
> 
> but
> 
>    type API_Morph_Value is new Interfaces.C.unsigned;
> 
> so others => <> isn't a legal expression for an API_Morph_Value; you
> should say
> 
>       API_Morph_Value'(0));
> 
> 
> There is still a bug, which ought to be fixed, but it's that GNAT has
> failed to recognise the actual problem and has got fatally confused.

Thanks, very much appreciated. 
I now have my main program building without crashing GNAT.
I'll also update my bug report with this information. 

^ permalink raw reply	[relevance 0%]

* Re: AdaCore Community 2018 Bugs
  2018-08-12 16:37  6%             ` Simon Wright
@ 2018-08-13  2:02  4%               ` Roger
  2018-08-13  2:54  0%               ` Roger
  1 sibling, 0 replies; 144+ results
From: Roger @ 2018-08-13  2:02 UTC (permalink / raw)


On Monday, August 13, 2018 at 2:37:52 AM UTC+10, Simon Wright wrote:
> Roger <rogermcm2@gmail.com> writes:
> 
> > On Sunday, August 12, 2018 at 5:33:35 PM UTC+10, Simon Wright wrote:
> >> Roger <rogermcm2@gmail.com> writes:
> >> 
> >> > As it now occurs even with GCC 6.1.0 I'm thinking it most likely has
> >> > to do with recent OSX changes.
> >> 
> >> Since it occurs on Debian Stretch, GCC 6.3.0, it can't be just macOS.
> >> 
> >> The actual error reported can change with successive compilations
> >> (sometimes it says something like 'undeclared variable ""', seems to
> >> settle on the CE), a surefire symptom of bad memory handling.
> >> 
> >> > This problem doesn't occur for compile only.
> >> > It occurs when I Build All from GPS
> >> 
> >> The error is a crash in the compiler, doesn't matter how you get there.
> >
> > I Have cut most of the code out of the test program but the crash
> > still occurs.  However, I am making progress on tracking back to the
> > minimal code where the crash first occurs.
> 
> The problem is in the packages Morph.Mesh_Morph_Value_Pointers,
> Mesh_Morph_Weight_Pointers.
> 
> You say
> 
>    package Mesh_Morph_Value_Pointers is new Interfaces.C.Pointers
>      (Interfaces.C.unsigned, API_Morph_Value, API_Morph_Values_Array,
>       API_Morph_Value'(others => <>));
> 
> but
> 
>    type API_Morph_Value is new Interfaces.C.unsigned;
> 
> so others => <> isn't a legal expression for an API_Morph_Value; you
> should say
> 
>       API_Morph_Value'(0));
> 
> 
> There is still a bug, which ought to be fixed, but it's that GNAT has
> failed to recognise the actual problem and has got fatally confused.


Thanks, very much appreciated.
I have made the change but still get the problem in my main program.
I'll check all my other new Interfaces.C.Pointers packages for similar errors.
I'll also update my bug report with this information.


^ permalink raw reply	[relevance 4%]

* Re: AdaCore Community 2018 Bugs
  @ 2018-08-12 16:37  6%             ` Simon Wright
  2018-08-13  2:02  4%               ` Roger
  2018-08-13  2:54  0%               ` Roger
  0 siblings, 2 replies; 144+ results
From: Simon Wright @ 2018-08-12 16:37 UTC (permalink / raw)


Roger <rogermcm2@gmail.com> writes:

> On Sunday, August 12, 2018 at 5:33:35 PM UTC+10, Simon Wright wrote:
>> Roger <rogermcm2@gmail.com> writes:
>> 
>> > As it now occurs even with GCC 6.1.0 I'm thinking it most likely has
>> > to do with recent OSX changes.
>> 
>> Since it occurs on Debian Stretch, GCC 6.3.0, it can't be just macOS.
>> 
>> The actual error reported can change with successive compilations
>> (sometimes it says something like 'undeclared variable ""', seems to
>> settle on the CE), a surefire symptom of bad memory handling.
>> 
>> > This problem doesn't occur for compile only.
>> > It occurs when I Build All from GPS
>> 
>> The error is a crash in the compiler, doesn't matter how you get there.
>
> I Have cut most of the code out of the test program but the crash
> still occurs.  However, I am making progress on tracking back to the
> minimal code where the crash first occurs.

The problem is in the packages Morph.Mesh_Morph_Value_Pointers,
Mesh_Morph_Weight_Pointers.

You say

   package Mesh_Morph_Value_Pointers is new Interfaces.C.Pointers
     (Interfaces.C.unsigned, API_Morph_Value, API_Morph_Values_Array,
      API_Morph_Value'(others => <>));

but

   type API_Morph_Value is new Interfaces.C.unsigned;

so others => <> isn't a legal expression for an API_Morph_Value; you
should say

      API_Morph_Value'(0));


There is still a bug, which ought to be fixed, but it's that GNAT has
failed to recognise the actual problem and has got fatally confused.


^ permalink raw reply	[relevance 6%]

* Re: Convert an access to constant to access to variable
  @ 2017-08-07 23:16  6%     ` Randy Brukardt
  0 siblings, 0 replies; 144+ results
From: Randy Brukardt @ 2017-08-07 23:16 UTC (permalink / raw)


"Victor Porton" <porton@narod.ru> wrote in message 
news:om500e$3iv$1@gioia.aioe.org...
...
> I need chars_ptr for interfacing with C.
>
> There is no constant_chars_ptr.
>
> (I need to generate chars_ptr from a char_array or rather from constant
> char_array.)

We did all of this sort of stuff just using Interfaces.C.To_Ada and various 
types with convention C. I don't think I've ever used Interfaces.C.Strings 
and Interfaces.C.Pointers outside of testing them. I think you are seeing 
why...

                                       Randy.


^ permalink raw reply	[relevance 6%]

* Re: Convert chars_ptr to Ada String
  2017-07-10 12:41  5%               ` Mark Lorenzen
@ 2017-07-10 14:24  4%                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 144+ results
From: Dmitry A. Kazakov @ 2017-07-10 14:24 UTC (permalink / raw)


On 10/07/2017 14:41, Mark Lorenzen wrote:
> On Monday, July 10, 2017 at 11:48:29 AM UTC+2, Dmitry A. Kazakov wrote:
>> On 10/07/2017 11:31, Victor Porton wrote:
>>
>>> Read description of Value() carefully. It stops at first NUL.
>>
>>      if Ptr = Null_Ptr then
>>         return "";
>>      else
>>         return To_Ada (Value (Ptr, Length), False);
>>      end if;
> 
> I don't think that it will work as (if I understand it correctly) the
> string the OP tries to convert may contain NULL characters that are
> not to be interpreted as string terminators.
I see, it seems that Value is broken in ARM B.3.1(35). The semantics 
specified is:

"If Item = Null_Ptr, then Value propagates Dereference_Error. Otherwise, 
Value returns the shorter of two arrays, either the first Length chars 
pointed to by Item, or Value(Item). The lower bound of the result is 0. 
If Length is 0, then Value propagates Constraint_Error."

which is if not useless then incomplete. There must be Trim_Nul or 
Ignore_Nul parameter as in To_Ada and Length=0 must be OK.

> I think the problem is, that the OP is confused about the difference
> between C strings and C arrays of characters and tries to use
> Interfaces.C.Strings to manipulate C arrays of characters thar are not
> be interpreted as C strings but as simple arrays of characters.

There is no such difference. Some C functions use NUL some ignore it. 
The OP's request is absolutely reasonable.

> Maybe Interfaces.C.Pointers is more appropriate?

Yes. There seems no way other than to use Interfaces.C.Pointers and 
convert each character individually.

I would suggest the OP to post a change request to ARG.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[relevance 4%]

* Re: Convert chars_ptr to Ada String
  @ 2017-07-10 12:41  5%               ` Mark Lorenzen
  2017-07-10 14:24  4%                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 144+ results
From: Mark Lorenzen @ 2017-07-10 12:41 UTC (permalink / raw)


On Monday, July 10, 2017 at 11:48:29 AM UTC+2, Dmitry A. Kazakov wrote:
> On 10/07/2017 11:31, Victor Porton wrote:
> 
> > Read description of Value() carefully. It stops at first NUL.
> 
>     if Ptr = Null_Ptr then
>        return "";
>     else
>        return To_Ada (Value (Ptr, Length), False);
>     end if;
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

I don't think that it will work as (if I understand it correctly) the string the OP tries to convert may contain NULL characters that are not to be interpreted as string terminators.

I think the problem is, that the OP is confused about the difference between C strings and C arrays of characters and tries to use Interfaces.C.Strings to manipulate C arrays of characters thar are not be interpreted as C strings but as simple arrays of characters.

Maybe Interfaces.C.Pointers is more appropriate?

Regards,

Mark L


^ permalink raw reply	[relevance 5%]

* Re: Convert chars_ptr to Ada String
  2017-07-10  4:58  0%         ` Anh Vo
@ 2017-07-10  9:31  0%           ` Victor Porton
    0 siblings, 1 reply; 144+ results
From: Victor Porton @ 2017-07-10  9:31 UTC (permalink / raw)


Anh Vo wrote:

> On Saturday, July 8, 2017 at 11:49:34 PM UTC-7, Victor Porton wrote:
>> Anh Vo wrote:
>> 
>> > On Friday, July 7, 2017 at 3:49:20 PM UTC-7, Victor Porton wrote:
>> >> Anh Vo wrote:
>> >> 
>> >> > On Friday, July 7, 2017 at 2:03:32 PM UTC-7, Victor Porton wrote:
>> >> >> Remind me how to convert a pair of Ptr: chars_ptr and Size: size_t
>> >> >> to an Ada string.
>> >> >> 
>> >> >> Ptr may contain NULs and this should not influence the length of
>> >> >> the resulting string.
>> >> > 
>> >> > Look at APIs defined in package Interfaces.C.Strings.
>> >> 
>> >> I've done it:
>> >> 
>> >> https://github.com/vporton/redland-bindings/blob/ada2012/ada/src/rdf-auxiliary-convert.adb
>> >> 
>> >> It requires not only Interfaces.C.Strings but also
>> >> Interfaces.C.Pointers to make things more confusing.
>> > 
>> > Why make it more confusing while it is actually simpler as shown below.
>> > 
>> > with Interfaces.C.Strings; use Interfaces.C.Strings;
>> > 
>> > package body RDF.Auxiliary.Convert is
>> > 
>> >    function Value_With_Possible_NULs (Item:
>> >    RDF.Auxiliary.C_Pointers.Pointer; Length: size_t) return String is
>> >    begin
>> >       return To_Ada(Item, Length);
>> 
>> I see no such two-argument To_Ada in Interfaces.C.
>> 
>> Or where to import such To_Ada from?
> 
> Oops! I meant function value which is defined in Interfaces.C.Strings.

Read description of Value() carefully. It stops at first NUL.

-- 
Victor Porton - http://portonvictor.org


^ permalink raw reply	[relevance 0%]

* Re: Convert chars_ptr to Ada String
  2017-07-09  6:49  0%       ` Victor Porton
@ 2017-07-10  4:58  0%         ` Anh Vo
  2017-07-10  9:31  0%           ` Victor Porton
  0 siblings, 1 reply; 144+ results
From: Anh Vo @ 2017-07-10  4:58 UTC (permalink / raw)


On Saturday, July 8, 2017 at 11:49:34 PM UTC-7, Victor Porton wrote:
> Anh Vo wrote:
> 
> > On Friday, July 7, 2017 at 3:49:20 PM UTC-7, Victor Porton wrote:
> >> Anh Vo wrote:
> >> 
> >> > On Friday, July 7, 2017 at 2:03:32 PM UTC-7, Victor Porton wrote:
> >> >> Remind me how to convert a pair of Ptr: chars_ptr and Size: size_t to
> >> >> an Ada string.
> >> >> 
> >> >> Ptr may contain NULs and this should not influence the length of the
> >> >> resulting string.
> >> > 
> >> > Look at APIs defined in package Interfaces.C.Strings.
> >> 
> >> I've done it:
> >> 
> >> https://github.com/vporton/redland-bindings/blob/ada2012/ada/src/rdf-auxiliary-convert.adb
> >> 
> >> It requires not only Interfaces.C.Strings but also Interfaces.C.Pointers
> >> to make things more confusing.
> > 
> > Why make it more confusing while it is actually simpler as shown below.
> > 
> > with Interfaces.C.Strings; use Interfaces.C.Strings;
> > 
> > package body RDF.Auxiliary.Convert is
> > 
> >    function Value_With_Possible_NULs (Item:
> >    RDF.Auxiliary.C_Pointers.Pointer; Length: size_t) return String is
> >    begin
> >       return To_Ada(Item, Length);
> 
> I see no such two-argument To_Ada in Interfaces.C.
> 
> Or where to import such To_Ada from?

Oops! I meant function value which is defined in Interfaces.C.Strings.


^ permalink raw reply	[relevance 0%]

* Re: Convert chars_ptr to Ada String
  2017-07-07 23:14  0%     ` Anh Vo
@ 2017-07-09  6:49  0%       ` Victor Porton
  2017-07-10  4:58  0%         ` Anh Vo
  0 siblings, 1 reply; 144+ results
From: Victor Porton @ 2017-07-09  6:49 UTC (permalink / raw)


Anh Vo wrote:

> On Friday, July 7, 2017 at 3:49:20 PM UTC-7, Victor Porton wrote:
>> Anh Vo wrote:
>> 
>> > On Friday, July 7, 2017 at 2:03:32 PM UTC-7, Victor Porton wrote:
>> >> Remind me how to convert a pair of Ptr: chars_ptr and Size: size_t to
>> >> an Ada string.
>> >> 
>> >> Ptr may contain NULs and this should not influence the length of the
>> >> resulting string.
>> > 
>> > Look at APIs defined in package Interfaces.C.Strings.
>> 
>> I've done it:
>> 
>> https://github.com/vporton/redland-bindings/blob/ada2012/ada/src/rdf-auxiliary-convert.adb
>> 
>> It requires not only Interfaces.C.Strings but also Interfaces.C.Pointers
>> to make things more confusing.
> 
> Why make it more confusing while it is actually simpler as shown below.
> 
> with Interfaces.C.Strings; use Interfaces.C.Strings;
> 
> package body RDF.Auxiliary.Convert is
> 
>    function Value_With_Possible_NULs (Item:
>    RDF.Auxiliary.C_Pointers.Pointer; Length: size_t) return String is
>    begin
>       return To_Ada(Item, Length);

I see no such two-argument To_Ada in Interfaces.C.

Or where to import such To_Ada from?

>    end;
> 
> end RDF.Auxiliary.Convert;

-- 
Victor Porton - http://portonvictor.org

^ permalink raw reply	[relevance 0%]

* Re: Convert chars_ptr to Ada String
  2017-07-07 22:48  5%   ` Victor Porton
@ 2017-07-07 23:14  0%     ` Anh Vo
  2017-07-09  6:49  0%       ` Victor Porton
  0 siblings, 1 reply; 144+ results
From: Anh Vo @ 2017-07-07 23:14 UTC (permalink / raw)


On Friday, July 7, 2017 at 3:49:20 PM UTC-7, Victor Porton wrote:
> Anh Vo wrote:
> 
> > On Friday, July 7, 2017 at 2:03:32 PM UTC-7, Victor Porton wrote:
> >> Remind me how to convert a pair of Ptr: chars_ptr and Size: size_t to an
> >> Ada string.
> >> 
> >> Ptr may contain NULs and this should not influence the length of the
> >> resulting string.
> > 
> > Look at APIs defined in package Interfaces.C.Strings.
> 
> I've done it:
> 
> https://github.com/vporton/redland-bindings/blob/ada2012/ada/src/rdf-auxiliary-convert.adb
> 
> It requires not only Interfaces.C.Strings but also Interfaces.C.Pointers
> to make things more confusing.

Why make it more confusing while it is actually simpler as shown below.

with Interfaces.C.Strings; use Interfaces.C.Strings;

package body RDF.Auxiliary.Convert is

   function Value_With_Possible_NULs (Item: RDF.Auxiliary.C_Pointers.Pointer; Length: size_t) return String is
   begin
      return To_Ada(Item, Length);
   end;

end RDF.Auxiliary.Convert;


^ permalink raw reply	[relevance 0%]

* Re: Convert chars_ptr to Ada String
  @ 2017-07-07 22:48  5%   ` Victor Porton
  2017-07-07 23:14  0%     ` Anh Vo
  0 siblings, 1 reply; 144+ results
From: Victor Porton @ 2017-07-07 22:48 UTC (permalink / raw)


Anh Vo wrote:

> On Friday, July 7, 2017 at 2:03:32 PM UTC-7, Victor Porton wrote:
>> Remind me how to convert a pair of Ptr: chars_ptr and Size: size_t to an
>> Ada string.
>> 
>> Ptr may contain NULs and this should not influence the length of the
>> resulting string.
> 
> Look at APIs defined in package Interfaces.C.Strings.

I've done it:

https://github.com/vporton/redland-bindings/blob/ada2012/ada/src/rdf-auxiliary-convert.adb

It requires not only Interfaces.C.Strings but also Interfaces.C.Pointers
to make things more confusing.

-- 
Victor Porton - http://portonvictor.org


^ permalink raw reply	[relevance 5%]

* Re: Interfaces.C + generics: stack overflow
  @ 2017-03-25 15:23  4%         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 144+ results
From: Dmitry A. Kazakov @ 2017-03-25 15:23 UTC (permalink / raw)


On 2017-03-25 15:17, hreba wrote:
> On 03/24/2017 11:03 PM, Dmitry A. Kazakov wrote:
>
> Thanks for your convincing suggestions and the detailed code. I changed
> my program accordingly - still STORAGE_ERROR.
>
> Then I followed the advice from Randy, transferring the exported
> function of the C library to another, non-generic package, changing the
> first parameter from
>
>    function gsl_integration_qng
>      (f: in out GSL_Function; ...
> to
>    function gsl_integration_qng
>      (f: System.Address; ...
>
> Result - STORAGE_ERROR

1. You could try to replace out T with access T. Especially because you 
apply a conversion to the argument.

2. You should also read the library documentation for memory allocation 
issues. Storage_Error is a usual result when an Ada allocated object is 
passed where a C malloc result expected. If some of the arguments are 
allocated by callee to be freed by the caller or conversely you must use 
Interfaces.C.Pointers to deal with these.

3. And you could debug it to get an idea where it fails. If the stack 
frame becomes corrupted, that means wrong call convention. An error in 
the heap indicates an allocator issue as above etc.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[relevance 4%]

* Re: Interfaces.C questions
  2017-03-19 12:17  4%   ` hreba
@ 2017-03-20  9:44  0%     ` Leo Brewin
  0 siblings, 0 replies; 144+ results
From: Leo Brewin @ 2017-03-20  9:44 UTC (permalink / raw)


Hi Frank,

Many thanks for sharing that code. I've wanted to play with GSL for a while but couldn't make sense of the C parameters and how to connect them back to Ada. Thanks again.

Cheers,
Leo

On Sunday, March 19, 2017 at 11:17:37 PM UTC+11, hreba wrote:
> On 03/19/2017 12:24 AM, Leo Brewin wrote:
> > Hi Frank,
> >
> > I'd be really interested to see a minimal working example once you've got it running.
> > I'd like to be able to use GSL in my own codes.
> >
> > Cheers,
> > Leo
> >
> 
> Ok, below follows my first working example, numerical quadrature. Any 
> critics is welcome. Some remarks:
> 
> 'void * params' in C can be a pointer to just anything, a number, an 
> array, a record. The best solution probably would be  a generic package 
> where the actual type is passed as parameter (see type Element in 
> Interfaces.C.Pointers). The quadrature algorithm I chose makes no use of 
> these parameters, so in my example I translate the type to 'access all 
> Integer' and pass null as value.
> 
> As I am beginning to build a numerics library, I will now
> 
>   - make the package generic, with 2 type parameters, one for the reals
>     (digits <>) and one for the parameters (private),
>   - write wrappers so that the client needs no Interfaces.C, and that he
>     can pass a function of
>     'type Real_Function is access function (x: Real) return Real;'
>     to the quadrature procedure instead of a record.
> 
> So here comes my example. The interface package is (no body):
> 
> -----------------------------------------------------------------------
> with Interfaces.C;
> 
> package GSL is
> 
>     package C renames Interfaces.C;
> 
>     type Void_Ptr is access all Integer;
>     type GSL_Function_Ptr is access
>       function (x: C.double; params: Void_Ptr) return C.double;
>     type GSL_Function is record
>        func:	GSL_Function_Ptr;
>        params:	Void_Ptr;
>     end record;
> 
> 
>     function Integration_QNG
>       (f: access GSL_Function;
>        a, b, epsabs, epsrel: C.double;
>        result, abserr: out C.double;
>        neval: out C.size_t)
>       return C.int;
> 
> private
> 
>     pragma Import (C, Integration_QNG, "gsl_integration_qng");
>     pragma Convention (C, Void_Ptr);
>     pragma Convention (C, GSL_Function_Ptr);
>     pragma Convention (C, GSL_Function);
> 
> end GSL;
> -----------------------------------------------------------------------------
> 
> The main subprogram (client) is
> 
> -----------------------------------------------------------------------------
> with Ada.Text_IO;	use Ada.Text_IO;
> with GSL;
> with Integ_Aux;
> 
> procedure Test_Integration
> is
>     use type GSL.C.double;
>     a:		GSL.C.double;
>     abserr:	GSL.C.double;
>     neval:	GSL.C.size_t;
>     res:		GSL.C.int;
>     gslf:	aliased GSL.GSL_Function;
> 
> begin
>     gslf.func:= Integ_Aux.Circle'Access;
>     gslf.params:= null;
>     res:= GSL.Integration_QNG
>       (gslf'Access, 0.0, 1.0, 0.001, 0.001, a, abserr, neval);
>     Put_Line("4*int_0^1 sqrt(1-x^2) dx = " & GSL.C.double'Image(4.0*a));
>     Put_Line(GSL.C.size_t'Image(neval) & " function evaluations, " &
> 	      GSL.C.double'Image(abserr) & " abs. error");
> end Test_Integration;
> ------------------------------------------------------------------------------
> Because an access is passed to the function to be integrated it has to 
> be in a separated package:
> ------------------------------------------------------------------------------
> with GSL;
> 
> package Integ_Aux is
>        function Circle (x: GSL.C.double; pars: GSL.Void_Ptr) return 
> GSL.C.double;
> 
> private
>     pragma Convention (C, Circle);
> end Integ_Aux;
> -------------------------------------------------------------------------------
> -------------------------------------------------------------------------------
> with Ada.Numerics.Generic_Elementary_Functions;
> with GSL;
> 
> package body Integ_Aux is
> 
>     package Functions is new
>       Ada.Numerics.Generic_Elementary_Functions (GSL.C.double);
> 
>     function Circle (x: GSL.C.double; pars: GSL.Void_Ptr) return 
> GSL.C.double is
>     use type GSL.C.double;
>     begin return Functions.Sqrt(abs(1.0-x*x));
>     end Circle;
> 
> end Integ_Aux;
> --------------------------------------------------------------------------------
> The project files of the interface package are
> --------------------------------------------------------------------------------
> -- External library "Gnu Scientific Library"
> 
> with "gslcblas";
> 
> Project GSL is
> 
>     type OS_Type is ("linux", "linux-gnu", "windows", "unknown");
>     act_os: OS_Type:= external ("OSTYPE");
>     -- act_os: OS_Type:= external ("OS_TYPE");
> 
>     For externally_built use "true";
>     For library_dir use "/usr/lib";
>     case act_os is
>        when "linux"|"linux-gnu" => for library_dir use "/usr/lib";
>        when "windows" => for library_dir use "/Lib/GSL";
>        when "unknown" => for Source_Dirs use ("/");	-- just anything
>     end case;
>     For library_name use "gsl";
>     For source_dirs use (); -- no sources.
>     -- For library_kind use "static";
>     -- if it is a static lib .a
> 
>     for library_kind use "dynamic";
>     -- if it is an so.
> 
> end GSL;
> -------------------------------------------------------------------------
> -------------------------------------------------------------------------
> -- External library "Gnu Scientific Library"
> 
> 
> Project GSLCBLAS is
> 
>     type OS_Type is ("linux", "linux-gnu", "windows", "unknown");
>     act_os: OS_Type:= external ("OSTYPE");
>     -- act_os: OS_Type:= external ("OS_TYPE");
> 
>     For externally_built use "true";
>     case act_os is
>        when "linux"|"linux-gnu" => for library_dir use "/usr/lib";
>        when "windows" => for library_dir use "/Lib/GSL";
>        when "unknown" => for Source_Dirs use ("/");	-- just anything
>     end case;
>     For library_name use "gslcblas";
>     For source_dirs use (); -- no sources.
>     -- For library_kind use "static";
>     -- if it is a static lib .a
> 
>     for library_kind use "dynamic";
>     -- if it is an so.
> 
> end GSLCBLAS;
> -----------------------------------------------------------------------------
> I tried to make these projects platform independent (Linux and Windows 
> so far); only tested on Linux so far. The environment variable OSTYPE 
> must exist. If you don't want to do this, just type
> for library_dir use "/usr/lib";
> instead of the 'case' construct (on Linux).
> Finally the project file for the main program:
> -----------------------------------------------------------------------------
> with "../../gsl.gpr";
> 
> project Test_Integration is
> 
>     for Source_Dirs use (".", "../../src"); -- test and interface sources
>     for Object_Dir use "../obj";
>     for Exec_Dir use ".";
>     for Main use ("test_integration.adb");
> 
>     package Compiler is
>        for Default_Switches ("ada") use ("-g", "-gnatf", "-gnat2012");
>     end Compiler;
> 
>     package Linker is
>        for Default_Switches ("ada") use ("-g");
>     end Linker;
> 
>     package Builder is
>        for Default_Switches ("ada") use ("-g");
>     end Builder;
> 
> end Test_Integration;
> ------------------------------------------------------------------------------
> The result is an approximation of the unit circle area, pi.
> 
> -- 
> Frank Hrebabetzky		+49 / 6355 / 989 5070

^ permalink raw reply	[relevance 0%]

* Re: Interfaces.C questions
  @ 2017-03-19 12:17  4%   ` hreba
  2017-03-20  9:44  0%     ` Leo Brewin
  0 siblings, 1 reply; 144+ results
From: hreba @ 2017-03-19 12:17 UTC (permalink / raw)


On 03/19/2017 12:24 AM, Leo Brewin wrote:
> Hi Frank,
>
> I'd be really interested to see a minimal working example once you've got it running.
> I'd like to be able to use GSL in my own codes.
>
> Cheers,
> Leo
>

Ok, below follows my first working example, numerical quadrature. Any 
critics is welcome. Some remarks:

'void * params' in C can be a pointer to just anything, a number, an 
array, a record. The best solution probably would be  a generic package 
where the actual type is passed as parameter (see type Element in 
Interfaces.C.Pointers). The quadrature algorithm I chose makes no use of 
these parameters, so in my example I translate the type to 'access all 
Integer' and pass null as value.

As I am beginning to build a numerics library, I will now

  - make the package generic, with 2 type parameters, one for the reals
    (digits <>) and one for the parameters (private),
  - write wrappers so that the client needs no Interfaces.C, and that he
    can pass a function of
    'type Real_Function is access function (x: Real) return Real;'
    to the quadrature procedure instead of a record.

So here comes my example. The interface package is (no body):

-----------------------------------------------------------------------
with Interfaces.C;

package GSL is

    package C renames Interfaces.C;

    type Void_Ptr is access all Integer;
    type GSL_Function_Ptr is access
      function (x: C.double; params: Void_Ptr) return C.double;
    type GSL_Function is record
       func:	GSL_Function_Ptr;
       params:	Void_Ptr;
    end record;


    function Integration_QNG
      (f: access GSL_Function;
       a, b, epsabs, epsrel: C.double;
       result, abserr: out C.double;
       neval: out C.size_t)
      return C.int;

private

    pragma Import (C, Integration_QNG, "gsl_integration_qng");
    pragma Convention (C, Void_Ptr);
    pragma Convention (C, GSL_Function_Ptr);
    pragma Convention (C, GSL_Function);

end GSL;
-----------------------------------------------------------------------------

The main subprogram (client) is

-----------------------------------------------------------------------------
with Ada.Text_IO;	use Ada.Text_IO;
with GSL;
with Integ_Aux;

procedure Test_Integration
is
    use type GSL.C.double;
    a:		GSL.C.double;
    abserr:	GSL.C.double;
    neval:	GSL.C.size_t;
    res:		GSL.C.int;
    gslf:	aliased GSL.GSL_Function;

begin
    gslf.func:= Integ_Aux.Circle'Access;
    gslf.params:= null;
    res:= GSL.Integration_QNG
      (gslf'Access, 0.0, 1.0, 0.001, 0.001, a, abserr, neval);
    Put_Line("4*int_0^1 sqrt(1-x^2) dx = " & GSL.C.double'Image(4.0*a));
    Put_Line(GSL.C.size_t'Image(neval) & " function evaluations, " &
	      GSL.C.double'Image(abserr) & " abs. error");
end Test_Integration;
------------------------------------------------------------------------------
Because an access is passed to the function to be integrated it has to 
be in a separated package:
------------------------------------------------------------------------------
with GSL;

package Integ_Aux is
       function Circle (x: GSL.C.double; pars: GSL.Void_Ptr) return 
GSL.C.double;

private
    pragma Convention (C, Circle);
end Integ_Aux;
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
with Ada.Numerics.Generic_Elementary_Functions;
with GSL;

package body Integ_Aux is

    package Functions is new
      Ada.Numerics.Generic_Elementary_Functions (GSL.C.double);

    function Circle (x: GSL.C.double; pars: GSL.Void_Ptr) return 
GSL.C.double is
    use type GSL.C.double;
    begin return Functions.Sqrt(abs(1.0-x*x));
    end Circle;

end Integ_Aux;
--------------------------------------------------------------------------------
The project files of the interface package are
--------------------------------------------------------------------------------
-- External library "Gnu Scientific Library"

with "gslcblas";

Project GSL is

    type OS_Type is ("linux", "linux-gnu", "windows", "unknown");
    act_os: OS_Type:= external ("OSTYPE");
    -- act_os: OS_Type:= external ("OS_TYPE");

    For externally_built use "true";
    For library_dir use "/usr/lib";
    case act_os is
       when "linux"|"linux-gnu" => for library_dir use "/usr/lib";
       when "windows" => for library_dir use "/Lib/GSL";
       when "unknown" => for Source_Dirs use ("/");	-- just anything
    end case;
    For library_name use "gsl";
    For source_dirs use (); -- no sources.
    -- For library_kind use "static";
    -- if it is a static lib .a

    for library_kind use "dynamic";
    -- if it is an so.

end GSL;
-------------------------------------------------------------------------
-------------------------------------------------------------------------
-- External library "Gnu Scientific Library"


Project GSLCBLAS is

    type OS_Type is ("linux", "linux-gnu", "windows", "unknown");
    act_os: OS_Type:= external ("OSTYPE");
    -- act_os: OS_Type:= external ("OS_TYPE");

    For externally_built use "true";
    case act_os is
       when "linux"|"linux-gnu" => for library_dir use "/usr/lib";
       when "windows" => for library_dir use "/Lib/GSL";
       when "unknown" => for Source_Dirs use ("/");	-- just anything
    end case;
    For library_name use "gslcblas";
    For source_dirs use (); -- no sources.
    -- For library_kind use "static";
    -- if it is a static lib .a

    for library_kind use "dynamic";
    -- if it is an so.

end GSLCBLAS;
-----------------------------------------------------------------------------
I tried to make these projects platform independent (Linux and Windows 
so far); only tested on Linux so far. The environment variable OSTYPE 
must exist. If you don't want to do this, just type
for library_dir use "/usr/lib";
instead of the 'case' construct (on Linux).
Finally the project file for the main program:
-----------------------------------------------------------------------------
with "../../gsl.gpr";

project Test_Integration is

    for Source_Dirs use (".", "../../src"); -- test and interface sources
    for Object_Dir use "../obj";
    for Exec_Dir use ".";
    for Main use ("test_integration.adb");

    package Compiler is
       for Default_Switches ("ada") use ("-g", "-gnatf", "-gnat2012");
    end Compiler;

    package Linker is
       for Default_Switches ("ada") use ("-g");
    end Linker;

    package Builder is
       for Default_Switches ("ada") use ("-g");
    end Builder;

end Test_Integration;
------------------------------------------------------------------------------
The result is an approximation of the unit circle area, pi.

-- 
Frank Hrebabetzky		+49 / 6355 / 989 5070


^ permalink raw reply	[relevance 4%]

* Re: A suggestion about interfacing with C
  2016-05-02 16:45  4% A suggestion about interfacing with C mockturtle
  2016-05-02 19:07  0% ` Jeffrey R. Carter
@ 2016-05-02 19:40  0% ` Per Sandberg
  1 sibling, 0 replies; 144+ results
From: Per Sandberg @ 2016-05-02 19:40 UTC (permalink / raw)


Well
I would have done it in two steps
1) generate a full low-level interface using -fdump-ada-spec
2) Do the high level interface using the generated specs in the private 
part.
I usually use a script like the following:
##################################################################################
#!/bin/bash
mkdir -p .gen
rm -rf src/gen
mkdir -p src/gen

(cd /usr/include/ ; find libnl3/ -type f -name "*.h")  | \
		grep -v -e qdisc/hfsc.h  \
				-e netlink/hashtable.h \
				-e route/link/info-api.h \
				-e route/link/sit.h \
				-e route/tc-api.h \
				-e route/link/api.h \
				-e route/link/ip6tnl.h \
				-e netlink/cache-api.h | sed -e "s-^-#include <-" -e "s-\$->-" | 
while read i ; do
	echo $i >.gen/gen.cpp
	(cd .gen; gcc -I /usr/include/libnl3/ -c -fdump-ada-spec gen.cpp)
done

# patch up all standard stuff (size_t, int32, uint32, ...)
# Get rid of dependencies to bits_*.h ctype.h ans alike.
sed -f sed sed/all.sed .gen/*.ads -i

# And file specific patches.
for i in sed/*.sed ; do
	name=$(basename $i .sed).ads
	echo .gen/$name
	if [[ -e ${name} ]] ; then
		sed -f $i -i ${name}
	fi
done

cp .gen/libnl3_* src/gen
##################################################################################

Den 2016-05-02 kl. 18:45, skrev mockturtle:
> Dear all,
> I need to interface with a C library (libnl, for using Netlink in Linux).  The library provides a "socket" represented by a struct nl_sock, but the user (the library user, that is, myself) sees only a pointer to nl_sock, since the library provides constructors, destructors and everything is needed to manipulate the socket. In a sense, the user can consider the pointer just as an "opaque handler" rather than a pointer. (I must say that my first impression of the API is definitively positive).
>
> In Ada I would like to provide a slightly thick package that hides the C type behind a, say, Netlink_Socket type that could be a record holding the pointer to nl_sock. Note that since libnl uses said pointer as an opaque handle, I just need to store the "bitstring" representing its value, in order to pass it to the C library.
>
> I was wandering about the best way to implement the Ada "view"  of the pointer to nl_sock.
>
> * I could use Interfaces.C.Pointers, but it seems me an overkill since I do not need to do pointer arithmetic.  Moreover, I would need to define a record equivalento to struct nl_sock (although maybe in my case a null record could suffice)
>
> * I could convert it in C to a char* and then using Interfaces.C.Strings.  (A bit dirty, but not too much...)
>
> * I could convert it to an integer... (no, definitively too dirty)
>
> * others?
>
> What would you suggest?
>
> Keep in mind that the software will run on Linux only (Netlink is specific to Linux, as long as I know) and at 99.99% only on x86 and similar.
>
> Thank you in advance for your help
>
> Riccardo
>

^ permalink raw reply	[relevance 0%]

* Re: A suggestion about interfacing with C
  2016-05-02 16:45  4% A suggestion about interfacing with C mockturtle
@ 2016-05-02 19:07  0% ` Jeffrey R. Carter
  2016-05-02 19:40  0% ` Per Sandberg
  1 sibling, 0 replies; 144+ results
From: Jeffrey R. Carter @ 2016-05-02 19:07 UTC (permalink / raw)


On 05/02/2016 09:45 AM, mockturtle wrote:
>
> I need to interface with a C library (libnl, for using Netlink in Linux).  The library provides a "socket" represented by a struct nl_sock, but the user (the library user, that is, myself) sees only a pointer to nl_sock, since the library provides constructors, destructors and everything is needed to manipulate the socket. In a sense, the user can consider the pointer just as an "opaque handler" rather than a pointer. (I must say that my first impression of the API is definitively positive).
>
> In Ada I would like to provide a slightly thick package that hides the C type behind a, say, Netlink_Socket type that could be a record holding the pointer to nl_sock. Note that since libnl uses said pointer as an opaque handle, I just need to store the "bitstring" representing its value, in order to pass it to the C library.

The 1st question is, "How many objects of this type are there in a typical 
application?" Very often in C, you find a type like this even though it makes no 
sense to have more than one of them, because the language lacks modules. If this 
is one of those cases where there will only be one of them, then the Ada 
implementation would be a pkg providing only operations, with the C pointer 
hidden in the body.

This doesn't address your low-level question, which is

> I was wandering about the best way to implement the Ada "view"  of the pointer to nl_sock.
>
> * I could use Interfaces.C.Pointers, but it seems me an overkill since I do not need to do pointer arithmetic.  Moreover, I would need to define a record equivalento to struct nl_sock (although maybe in my case a null record could suffice)
>
> * I could convert it in C to a char* and then using Interfaces.C.Strings.  (A bit dirty, but not too much...)
>
> * I could convert it to an integer... (no, definitively too dirty)
>
> * others?

This kind of opaque pointer is very common in C libraries. Some use "void*" to 
further hide the implementation details. I think you're over thinking things 
here. I usually do something like

type C_Socket is null record;
pragma Convention (C, C_Socket);

type Socket_Ptr is access all C_Socket;
pragma Convention (C, Socket_Ptr);

If you're hiding this in the pkg body, then you're done. If you're exposing the 
type, then these would be in the private part and you'll have

type Socket [(...)] is limited private;

in the public part. Also in the private part you'd have

type Socket [(...)] is limited record
    Ptr : Socket_Ptr;
end record;

or maybe even

function New_Socket [(...)] return Socket_Ptr;
pragma Import (C, New_Socket, ...);

type Socket [(...)] is limited record
    Ptr : Socket_Ptr := New_Socket [(...)];
end record;

Of course, if finalization is needed, this becomes a little more complex, as 
does initialization that needs parameters that can't be discriminants.

-- 
Jeff Carter
"When Roman engineers built a bridge, they had to stand under it
while the first legion marched across. If programmers today
worked under similar ground rules, they might well find
themselves getting much more interested in Ada!"
Robert Dewar
62


^ permalink raw reply	[relevance 0%]

* A suggestion about interfacing with C
@ 2016-05-02 16:45  4% mockturtle
  2016-05-02 19:07  0% ` Jeffrey R. Carter
  2016-05-02 19:40  0% ` Per Sandberg
  0 siblings, 2 replies; 144+ results
From: mockturtle @ 2016-05-02 16:45 UTC (permalink / raw)


Dear all,
I need to interface with a C library (libnl, for using Netlink in Linux).  The library provides a "socket" represented by a struct nl_sock, but the user (the library user, that is, myself) sees only a pointer to nl_sock, since the library provides constructors, destructors and everything is needed to manipulate the socket. In a sense, the user can consider the pointer just as an "opaque handler" rather than a pointer. (I must say that my first impression of the API is definitively positive). 

In Ada I would like to provide a slightly thick package that hides the C type behind a, say, Netlink_Socket type that could be a record holding the pointer to nl_sock. Note that since libnl uses said pointer as an opaque handle, I just need to store the "bitstring" representing its value, in order to pass it to the C library.

I was wandering about the best way to implement the Ada "view"  of the pointer to nl_sock.  

* I could use Interfaces.C.Pointers, but it seems me an overkill since I do not need to do pointer arithmetic.  Moreover, I would need to define a record equivalento to struct nl_sock (although maybe in my case a null record could suffice)

* I could convert it in C to a char* and then using Interfaces.C.Strings.  (A bit dirty, but not too much...)

* I could convert it to an integer... (no, definitively too dirty)

* others? 

What would you suggest?

Keep in mind that the software will run on Linux only (Netlink is specific to Linux, as long as I know) and at 99.99% only on x86 and similar.

Thank you in advance for your help

Riccardo


^ permalink raw reply	[relevance 4%]

* Re: How to convert a C "char *" value to Ada string?
  @ 2014-07-22  0:28  6% ` Randy Brukardt
  0 siblings, 0 replies; 144+ results
From: Randy Brukardt @ 2014-07-22  0:28 UTC (permalink / raw)


"Victor Porton" <porton@narod.ru> wrote in message 
news:lqk8lm$hss$1@speranza.aioe.org...
> How to convert a C "char *" value to Ada string?
>
> There is
>
>   function To_Ada (Item     : in char_array;
>                    Trim_Nul : in Boolean := True)
>      return String;
>
> in package Interfaces.C, but it receives an array not a pointer (= 
> access).
>
> So I don't understand how to do this simple thing.

You didn't look far enough in the RM. Look at Interfaces.C.Strings and/or 
Interfaces.C.Pointers (B.3.1 and B.3.2, respectively). You probably want 
Interfaces.C.Strings.

                     Randy. 


^ permalink raw reply	[relevance 6%]

* Re: abstract types and subprograms
  2014-05-20 11:55  0% ` Dmitry A. Kazakov
@ 2014-05-20 12:28  0%   ` Victor Porton
  0 siblings, 0 replies; 144+ results
From: Victor Porton @ 2014-05-20 12:28 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> On Tue, 20 May 2014 13:22:30 +0300, Victor Porton wrote:
> 
>> By the philosophy of programming From_Handle should be non-abstract but
>> return an abstract object, and From_Handle should be automatically
>> overridden for descendants non-abstract objects.
>> 
>> What is wrong?
> 
> You cannot automatically override without knowing the implementation,
> which you don't in advance. If you know it, then it is same for all class.
> See below.
> 
>> -- rdf-base.ads
>> with Ada.Finalization;
>> with Interfaces.C.Pointers;
>> 
>> package RDF.Base is
>> 
>>    -- Internal
>>    type Dummy_Record is null record;
>> 
>>    -- Internal
>>    type Dummy_Record_Access is access Dummy_Record;
>>    
>>    type Base_Object is abstract new Ada.Finalization.Limited_Controlled
>>    with
>> private;
>>    
>>    function Get_Handle(Object: Base_Object) return Dummy_Record_Access
>>    with
>> Inline;
>>    
>>    function From_Handle(Handle: Dummy_Record_Access) return Base_Object
>>    with
>> Inline;
> 
> function From_Handle(Handle: Dummy_Record_Access) return
> Base_Object'Class;
> 
> Logically, a handle can point on an object of any type derived from
> Base_Object, so it is a class.

But can this:

   function From_Handle(Handle: Dummy_Record_Access) return Base_Object is
      (Ada.Finalization.Limited_Controlled with Handle=>Handle);

be implemented if the return type changes to Base_Object'Class?

It seems for me that I should define it as above and override From_Handle 
for each derived tagged type.

It seems that returning Base_Object'Class wouldn't magically make it work 
(without explicit override).

Or can it be done implementing Frorm_Handle only once (for Base_Object) with 
automatic changing its signature for derived tagged types?

-- 
Victor Porton - http://portonvictor.org

^ permalink raw reply	[relevance 0%]

* Re: abstract types and subprograms
  2014-05-20 10:22  4% abstract types and subprograms Victor Porton
@ 2014-05-20 11:55  0% ` Dmitry A. Kazakov
  2014-05-20 12:28  0%   ` Victor Porton
  0 siblings, 1 reply; 144+ results
From: Dmitry A. Kazakov @ 2014-05-20 11:55 UTC (permalink / raw)


On Tue, 20 May 2014 13:22:30 +0300, Victor Porton wrote:

> By the philosophy of programming From_Handle should be non-abstract but 
> return an abstract object, and From_Handle should be automatically 
> overridden for descendants non-abstract objects.
> 
> What is wrong?

You cannot automatically override without knowing the implementation, which
you don't in advance. If you know it, then it is same for all class. See
below.

> -- rdf-base.ads
> with Ada.Finalization;
> with Interfaces.C.Pointers;
> 
> package RDF.Base is
> 
>    -- Internal
>    type Dummy_Record is null record;
> 
>    -- Internal
>    type Dummy_Record_Access is access Dummy_Record;
>    
>    type Base_Object is abstract new Ada.Finalization.Limited_Controlled with 
> private;
>    
>    function Get_Handle(Object: Base_Object) return Dummy_Record_Access with 
> Inline;
>    
>    function From_Handle(Handle: Dummy_Record_Access) return Base_Object with 
> Inline;

function From_Handle(Handle: Dummy_Record_Access) return Base_Object'Class;

Logically, a handle can point on an object of any type derived from
Base_Object, so it is a class.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[relevance 0%]

* abstract types and subprograms
@ 2014-05-20 10:22  4% Victor Porton
  2014-05-20 11:55  0% ` Dmitry A. Kazakov
  0 siblings, 1 reply; 144+ results
From: Victor Porton @ 2014-05-20 10:22 UTC (permalink / raw)


I am now an Ada novice. I started to write librdf bindings for Ada.

The following produces the error:

gnatmake -ws -c -u -P/home/porton/Projects/librdf-ada/librdf.gpr rdf-
base.adb
gcc-4.6 -c -g -O2 -gnat2012 -I- -gnatA /home/porton/Projects/librdf-ada/rdf-
base.adb
rdf-base.ads:20:04: function that returns abstract type must be abstract
gnatmake: "/home/porton/Projects/librdf-ada/rdf-base.adb" compilation error


By the philosophy of programming From_Handle should be non-abstract but 
return an abstract object, and From_Handle should be automatically 
overridden for descendants non-abstract objects.

What is wrong?


-- rdf-base.ads
with Ada.Finalization;
with Interfaces.C.Pointers;

package RDF.Base is

   -- Internal
   type Dummy_Record is null record;

   -- Internal
   type Dummy_Record_Access is access Dummy_Record;
   
   type Base_Object is abstract new Ada.Finalization.Limited_Controlled with 
private;
   
   function Get_Handle(Object: Base_Object) return Dummy_Record_Access with 
Inline;
   
   function From_Handle(Handle: Dummy_Record_Access) return Base_Object with 
Inline;
   
private
   
   type Base_Object is new Ada.Finalization.Limited_Controlled with
      record
         Handle: Dummy_Record_Access;
      end record;     
   
end RDF.Base;

-- rdf-base.adb
package body RDF.Base is
   
   function Get_Handle(Object: Base_Object) return Dummy_Record_Access is 
(Object.Handle);
   
   function From_Handle(Handle: Dummy_Record_Access) return Base_Object is
      (Ada.Finalization.Limited_Controlled with Handle=>Handle);
   
end RDF.Base;

-- 
Victor Porton - http://portonvictor.org


^ permalink raw reply	[relevance 4%]

* Re: How to import C pointers to structures?
  2014-05-20  0:10  4%     ` Shark8
@ 2014-05-20  0:22  5%       ` Adam Beneschan
  0 siblings, 0 replies; 144+ results
From: Adam Beneschan @ 2014-05-20  0:22 UTC (permalink / raw)


On Monday, May 19, 2014 5:10:14 PM UTC-7, Shark8 wrote:
> On 19-May-14 16:44, Adam Beneschan wrote:
> 
> >> You generally *can't*  do a real/meaningful import w/o knowing the
> >> layout.
> 
> > I'm not sure that's quite true ... there are lots of situations
> > where you simply want to "pass through" a pointer, e.g. in
> > callback situations, where a function sets up a callback and says
> > "when you do the callback, please pass this pointer to it"; and
> > whoever registers the callback will take the pointer, store it
> > somewhere, and use it when it's needed, without ever trying to
> > look at what it points to.
> 
> While those are /common/ cases, I would be hesitant to call them 
> /general/ cases.
> 
> > Unfortunately, I don't see the equivalent of "void *" anywhere in
> > Interfaces.C, which is what the sort of thing you'd want.  You
> > could probably use Interfaces.C.Strings.chars_ptr (the equivalent
> > of "char *").
> 
> Instantiate Interfaces.C.Pointers on a null-record or, perhaps, 
> System.Address?

I wouldn't trust System.Address; there's no guarantee that the Ada implementation of this Ada type is represented the same way as a C pointer, an Ada access object, or anything else.  The first idea, to instantiate Interfaces.C.Pointers, should be trustworthy--that's an excellent idea.

                               -- Adam

^ permalink raw reply	[relevance 5%]

* Re: How to import C pointers to structures?
  @ 2014-05-20  0:10  4%     ` Shark8
  2014-05-20  0:22  5%       ` Adam Beneschan
  0 siblings, 1 reply; 144+ results
From: Shark8 @ 2014-05-20  0:10 UTC (permalink / raw)


On 19-May-14 16:44, Adam Beneschan wrote:
>> You generally *can't*  do a real/meaningful import w/o knowing the
>> layout.
>
> I'm not sure that's quite true ... there are lots of situations
> where you simply want to "pass through" a pointer, e.g. in
> callback situations, where a function sets up a callback and says
> "when you do the callback, please pass this pointer to it"; and
> whoever registers the callback will take the pointer, store it
> somewhere, and use it when it's needed, without ever trying to
> look at what it points to.

While those are /common/ cases, I would be hesitant to call them 
/general/ cases.

> Unfortunately, I don't see the equivalent of "void *" anywhere in
> Interfaces.C, which is what the sort of thing you'd want.  You
> could probably use Interfaces.C.Strings.chars_ptr (the equivalent
> of "char *").

Instantiate Interfaces.C.Pointers on a null-record or, perhaps, 
System.Address?

^ permalink raw reply	[relevance 4%]

* Re: Thick bindings to a C library and gnattest: suggestions?
  2013-07-01 11:11  3%   ` Maurizio Tomasi
@ 2013-07-01 12:32  0%     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 144+ results
From: Dmitry A. Kazakov @ 2013-07-01 12:32 UTC (permalink / raw)


On Mon, 1 Jul 2013 04:11:55 -0700 (PDT), Maurizio Tomasi wrote:

>>> First question: the vectors used by the CFITSIO library are sometimes
>>> huge (millions of elements), sometimes very small (~ 10 elements).
>>> I decided to always allocate them on the heap, using declarations like
>>> these:
>> 
>> Why should bindings care about that?
> 
> Shouldn't they care? Perhaps I am missing something regarding the Ada
> language, in fact C++ does not care about whether an array is allocated on
> the stack or on the heap. But if I declare a function like the following:
> 
> function Read_Double_Array_From_FITS (File_Name : String) return Double_Array;
> 
> and I implement it in the following way:
> 
> --  Call the C functions that returns the number of rows in the file
> Num_Of_Elements := Get_Number_Of_Elements(FITS_File);
> declare
>   Vector_To_Return : Double_Array (1 .. Num_Of_Elements);
> begin
>   --  Call the C function that fills Vector_To_Return
>   ...
>   return Vector_To_Return;
> end;
> 
> then every time I read some huge array I will get a STORAGE_ERROR near the
> declaration of "Vector_To_Return". This is the reason why I declared the
> return type of "Read_Data_From_FITS" as a Double_Array_Ptr instead of a
> Double_Array, and implemented it as:
> 
> Num_Of_Elements := Get_Number_Of_Elements(FITS_File);
> declare
>   Vector_To_Return : Double_Array_Ptr;
> begin
>   Vector_To_Return := new Double_Array (1 .. Num_Of_Elements);
>   --  Call the C function that fills Vector_To_Return
>   ...
>   return Vector_To_Return;
> end;
> 
> Your answer makes me think there is a smarter way of avoiding the
> distinction between Double_Array_Ptr and Double_Array. (This would in fact
> make Ada much more like C++, where this distinction does not exist.) Is
> this the reason why in your example you declared Double_Array an array of
> *aliased* doubles? Or was your point just to use the address of its first member?

The first point is that it is not the objective of bindings to manage
memory. Of course, there could be bindings which do that, in which case you
would allocate objects transparently to the caller and have some garbage
collection schema behind opaque handles to the objects. This is a possible
design but it is not what you probably wanted. So let us take for granted
that it is the client's responsibility to allocate objects. In this case
the bindings shall work for any kind of objects allocated in any possible
memory pool, stack included.

Now, how would you do that? There are many ways.

1. Prior to Ada 2005, the usual method was one you find in
Ada.Text_IO.Get_Line. You use a procedure and a parameter telling how much
elements were written:

   procedure Read_Double_Array_From_FITS
       (A : in out Double_Array; Last : out Positive);

Here Last indicates the last element of A containing data. The
implementation would raise End_Error when there are more than A'Length
elements in A. Get_Line, for example, returns Last = A'Last meaning that
there is more to read. The caller uses A (A'First..Last) in further calls.

In my libraries I am using a slightly more universal approach:

   procedure Read_Double_Array_From_FITS
       (A : in out Double_Array; Pointer : in out Positive);

Here A (Pointer..A'Last) is where the result is stored and then Pointer is
advanced to the first element following the input. So the result is between
old pointer and new pointer - 1.

2. With Ada 2005 you can use return statement

   procedure Read_Double_Array_From_FITS return Double_Array is
   begin
       return Result : Double_Array (1..Get_Number_Of_Elements) do
           -- Fill Result here
       end return;
   end Read_Double_Array_From_FITS;

The caller is free to use this function with the allocator new:

   A : access Double_Array :=
           new Double_Array'(Read_Double_Array_From_FITS);

Theoretically the compiler could optimize temp object away. (You should
check if GNAT really does this)

Dealing with huge arrays I would prefer the approach #1. I would probably
allocate some scratch buffer and reuse it all over again.

Another approach is using #1 or #2 with some custom storage pool organized
as a stack or arena in order to minimize memory management overhead.

In any case, it is not the bindings' business.

> The fact that Ada arrays can have arbitrary bounds whom they
> carry is one of the things that made me interested towards Ada at the
> beginning. Why did you say this might be "troublesome"?

Because C arrays have none. When you want to pass an Ada array to C you
must flatten it. One way is to declare a subtype:

   procedure Bar (A : Double_Array) is
      subtype Flat is A (A'Range);
      B : Flat := ...;
   begin
      --- B does not have bounds and can be passed around as-is

Some pass pointer to the first element. After all, C's arrays are a
fiction.

Some use addresses. E.g. GtkAda bindings pass System.Address for any C
objects sparing headache of proper types. Purists would consider this
approach rather being sloppy.

> Given this context, is your suggestion of using Interfaces.C.Pointers still valid?

Yes.
 
>> Why don't you simply pass the array down to the C subprogram? You can do
>> something like:
>> 
>>    type Double_Array is array (Positive range <>)
>>       of aliased Interfaces.C.double;
>>    pragma Convention (C, Double_Array);
>>    procedure Foo (A : Double_Array);
>> 
>> Implementation:
>> 
>>    type Double_Ptr is access all Interfaces.C.double;
>>    pragma Convention (C, Double_Ptr);
>> 
>>    procedure Foo (A : Double_Array) is
>>    --
>>    -- Assuming foo's signature in C:
>>    --
>>    --    foo (double * a, unsigned n);
>>    --
>>       procedure Internal (A : Double_Ptr; N : Interfaces.C.unsigned);
>>       pragma Import (C, Internal, "foo");
>>    begin
>>       Internal (A (A'First)'Access, A'Length);
>>    end Foo;
> 
> But what if A'Length is so large that the array does not fit into the
> stack?

It is a client's problem. 

>>> I am sure there is some clever way to solve these two minor points,
>>> but so far I have not been able to find it. I tried e.g. to put
>>> "-lcfitsio" in the project file of the AdaFITS library, but with no
>>> success.
>> 
>> Make a library project file for cfitsio instead. "with" it from your
>> project. GNAT knows how to handle it and will add appropriate linker
>> switches to any project using it directly or indirectly. A library project
>> file could look like:
>> 
>> project cfitsio is
>>    for Externally_Built use "true"; -- Do not bother to compile me
>>    for Source_Files use (); -- No sources
>>    for Library_Dir use ".";   -- Where .llb, .a, .dll, .so are
>>    for Library_Name use "cfitsio"; -- Without "lib" prefix!
>>    for Library_Kind use "dynamic"; -- A DLL
>> end cfitsio;
> 
> This is really a good idea, I did not think about this! There are only two problems with this approach:
> 
> 1. The CFITSIO library is often compiled using ad-hoc flags in
> supercomputing facilities, in order to make it work better with the
> storage systems. I need to use the library provided by the system, not my
> own.

This is why Externally_Built is set true.

> 2. ...the system library is not always available as a dynamic .so file: in
> some cases I must statically link CFITSIO (the libcfitsio.so library is
> not available on every node of the cluster: when I discovered this, the
> system admin told me to link statically).

Then Library_Kind is "static". You can even have a scenario variable to
select if you wanted to link it statically or dynamically.
 
> Is there no other option?

There are other options, but they are incredibly intrusive, especially when
your bindings are themselves a library. Linker options are ignored for
library projects. They are not "transitive". I.e. each client project will
need to specify ever changing linker switches.

There is also a pragma for specify linker switches in the source code.
Which is obviously the worst maintenance nightmare one could ever
imagine...

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[relevance 0%]

* Re: Thick bindings to a C library and gnattest: suggestions?
  2013-07-01  9:45  6% ` Dmitry A. Kazakov
@ 2013-07-01 11:11  3%   ` Maurizio Tomasi
  2013-07-01 12:32  0%     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 144+ results
From: Maurizio Tomasi @ 2013-07-01 11:11 UTC (permalink / raw)


Hi Dmitry,

  Many thanks for your suggestions. You gave me a lot of things to think about.  I have a few questions about what you wrote.

> > First question: the vectors used by the CFITSIO library are sometimes
> > huge (millions of elements), sometimes very small (~ 10 elements).
> > I decided to always allocate them on the heap, using declarations like
> > these:
> 
> Why should bindings care about that?

Shouldn't they care? Perhaps I am missing something regarding the Ada language, in fact C++ does not care about whether an array is allocated on the stack or on the heap. But if I declare a function like the following:

function Read_Double_Array_From_FITS (File_Name : String) return Double_Array;

and I implement it in the following way:

--  Call the C functions that returns the number of rows in the file
Num_Of_Elements := Get_Number_Of_Elements(FITS_File);
declare
  Vector_To_Return : Double_Array (1 .. Num_Of_Elements);
begin
  --  Call the C function that fills Vector_To_Return
  ...
  return Vector_To_Return;
end;

then every time I read some huge array I will get a STORAGE_ERROR near the declaration of "Vector_To_Return". This is the reason why I declared the return type of "Read_Data_From_FITS" as a Double_Array_Ptr instead of a Double_Array, and implemented it as:

Num_Of_Elements := Get_Number_Of_Elements(FITS_File);
declare
  Vector_To_Return : Double_Array_Ptr;
begin
  Vector_To_Return := new Double_Array (1 .. Num_Of_Elements);
  --  Call the C function that fills Vector_To_Return
  ...
  return Vector_To_Return;
end;

Your answer makes me think there is a smarter way of avoiding the distinction between Double_Array_Ptr and Double_Array. (This would in fact make Ada much more like C++, where this distinction does not exist.) Is this the reason why in your example you declared Double_Array an array of *aliased* doubles? Or was your point just to use the address of its first member?

> Using unconstrained arrays could be troublesome because they contain
> bounds. You may consider the package B.3.2
> 
>    Interfaces.C.Pointers
> 
> But normally you do not need array pointers in bindings except for the
> cases when the C library stores the pointer to keep it after returning from
> the subprogram.

I need the C library only in those cases where I need to save/retrieve arrays of data from disk in binary format. But 100% of the calculations on the values stored in these arrays will be done using Ada code (e.g., loops...). The point of rewriting my C++ program in Ada is because my codes need to work with very large arrays (I am part of a large astrophysics project), and I find Ada arrays much more appealing than C++ vectors. The fact that Ada arrays can have arbitrary bounds whom they carry is one of the things that made me interested towards Ada at the beginning. Why did you say this might be "troublesome"?

Given this context, is your suggestion of using Interfaces.C.Pointers still valid?

> Why don't you simply pass the array down to the C subprogram? You can do
> something like:
> 
>    type Double_Array is array (Positive range <>)
>       of aliased Interfaces.C.double;
>    pragma Convention (C, Double_Array);
>    procedure Foo (A : Double_Array);
> 
> Implementation:
> 
>    type Double_Ptr is access all Interfaces.C.double;
>    pragma Convention (C, Double_Ptr);
> 
>    procedure Foo (A : Double_Array) is
>    --
>    -- Assuming foo's signature in C:
>    --
>    --    foo (double * a, unsigned n);
>    --
>       procedure Internal (A : Double_Ptr; N : Interfaces.C.unsigned);
>       pragma Import (C, Internal, "foo");
>    begin
>       Internal (A (A'First)'Access, A'Length);
>    end Foo;

But what if A'Length is so large that the array does not fit into the stack? Increasing the stack to a good value would be better than allocating objects on the heap? I would have problems in determining what size to use, as my code should work on a variety of systems (my laptop, supercomputing facilities...) and the amount of data it needs to load depends on the context.

> > I am sure there is some clever way to solve these two minor points,
> > but so far I have not been able to find it. I tried e.g. to put
> > "-lcfitsio" in the project file of the AdaFITS library, but with no
> > success.
> 
> Make a library project file for cfitsio instead. "with" it from your
> project. GNAT knows how to handle it and will add appropriate linker
> switches to any project using it directly or indirectly. A library project
> file could look like:
> 
> project cfitsio is
>    for Externally_Built use "true"; -- Do not bother to compile me
>    for Source_Files use (); -- No sources
>    for Library_Dir use ".";   -- Where .llb, .a, .dll, .so are
>    for Library_Name use "cfitsio"; -- Without "lib" prefix!
>    for Library_Kind use "dynamic"; -- A DLL
> end cfitsio;

This is really a good idea, I did not think about this! There are only two problems with this approach:

1. The CFITSIO library is often compiled using ad-hoc flags in supercomputing facilities, in order to make it work better with the storage systems. I need to use the library provided by the system, not my own. But...

2. ...the system library is not always available as a dynamic .so file: in some cases I must statically link CFITSIO (the libcfitsio.so library is not available on every node of the cluster: when I discovered this, the system admin told me to link statically).

Is there no other option? I searched the "gnattest" documentation for some way to prevent it from overwriting some parts of the files, but with no success.

Again, many thanks for your answers.
  Maurizio.

^ permalink raw reply	[relevance 3%]

* Re: Thick bindings to a C library and gnattest: suggestions?
  @ 2013-07-01  9:45  6% ` Dmitry A. Kazakov
  2013-07-01 11:11  3%   ` Maurizio Tomasi
  0 siblings, 1 reply; 144+ results
From: Dmitry A. Kazakov @ 2013-07-01  9:45 UTC (permalink / raw)


On Mon, 1 Jul 2013 02:02:34 -0700 (PDT), ziotom78@gmail.com wrote:

> First question: the vectors used by the CFITSIO library are sometimes
> huge (millions of elements), sometimes very small (~ 10 elements).
> I decided to always allocate them on the heap, using declarations like
> these:

Why should bindings care about that?

>    subtype Double is Interfaces.C.double;
>    type Double_Array is array (Positive range <>)
>      of Interfaces.C.double;
>    pragma Convention (C, Double_Array);
>    type Double_Array_Ptr is access Double_Array;

Using unconstrained arrays could be troublesome because they contain
bounds. You may consider the package B.3.2

   Interfaces.C.Pointers

which does this.

But normally you do not need array pointers in bindings except for the
cases when the C library stores the pointer to keep it after returning from
the subprogram.

> (similar declarations exist for arrays of integers/long...), and then
> using "new Double_Array" whenever I need to allocate room for an
> array. Every binding function only uses Double_Array_Ptr. Is this the best
> way to do this in Ada? Every text I read about Ada says to stay away
> from objects allocated on the heap, but I do not see any other
> solution here.

Why don't you simply pass the array down to the C subprogram? You can do
something like:

   type Double_Array is array (Positive range <>)
      of aliased Interfaces.C.double;
   pragma Convention (C, Double_Array);
   procedure Foo (A : Double_Array);

Implementation:

   type Double_Ptr is access all Interfaces.C.double;
   pragma Convention (C, Double_Ptr);

   procedure Foo (A : Double_Array) is
   --
   -- Assuming foo's signature in C:
   --
   --    foo (double * a, unsigned n);
   --
      procedure Internal (A : Double_Ptr; N : Interfaces.C.unsigned);
      pragma Import (C, Internal, "foo");
   begin
      Internal (A (A'First)'Access, A'Length);
   end Foo;

> I am sure there is some clever way to solve these two minor points,
> but so far I have not been able to find it. I tried e.g. to put
> "-lcfitsio" in the project file of the AdaFITS library, but with no
> success.

Make a library project file for cfitsio instead. "with" it from your
project. GNAT knows how to handle it and will add appropriate linker
switches to any project using it directly or indirectly. A library project
file could look like:

project cfitsio is
   for Externally_Built use "true"; -- Do not bother to compile me
   for Source_Files use (); -- No sources
   for Library_Dir use ".";   -- Where .llb, .a, .dll, .so are
   for Library_Name use "cfitsio"; -- Without "lib" prefix!
   for Library_Kind use "dynamic"; -- A DLL
end cfitsio;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[relevance 6%]

* Re: Memory Access
  @ 2011-11-07 21:26  4% ` Simon Wright
  0 siblings, 0 replies; 144+ results
From: Simon Wright @ 2011-11-07 21:26 UTC (permalink / raw)


awdorrin <awdorrin@gmail.com> writes:

> I understand that the Bounds_Ptr is being used to assign array
> constraints to the dope vector. But I'm guessing that GNAT doesn't
> define these dope vectors using this sort of definition.

It probably does, just not quite the same!

> I haven't done much development in Ada, so I'm at a loss here. I'm
> making the assumption that the way this code was implemented
> (somewhere between 1992 and 98) was not really the right way to
> approach this problem. But I'm not sure what method should be used,
> and haven't had much luck the past few days searching the web and
> newsgroups.

I wonder whether Interfaces.C.Pointers would be appropriate?

http://www.adaic.org/resources/add_content/standards/05rm/html/RM-B-3-2.html



^ permalink raw reply	[relevance 4%]

* Re: Address and bit mask
  @ 2011-08-30 12:35  5%       ` Georg Bauhaus
  0 siblings, 0 replies; 144+ results
From: Georg Bauhaus @ 2011-08-30 12:35 UTC (permalink / raw)


On 30.08.11 11:14, milouz wrote:

> Hum... well... I still do not know how to do some simple arithmetic
> with address.

As has been said, addresses are addresses of something.
The "something" which your pointers will refer to can
be addressed, aligned, and laid out very specifically
using the attribute functions and packages mentioned. OTOH...

> So, let me give you an example in C :
>
>   p = (char*) (((unsigned long)p + ALIGN_MASK) & ~ALIGN_MASK);

The only address arithmetic in there is ... I'm not sure,
have you got the parentheses right?

Assuming this from the Linux kernel source:

/*
 * Round up the ptr to an 8-byte boundary.
 */
#define ALIGN_MASK 7
static inline void *align_ptr(void *ptr)
{
        return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK);
}

(Which, incidentally, gives
test.c:8:34: warning: pointer of type �void *� used in arithmetic)

Assuming your program cannot control alignment using 'Alignment,
layout specifications, and offsets etc, as Ludovic has shown.
Cannot perform arithmetic on addresses using this function
from System.Storage_Elements:

        function "+"(Left : Address; Right : Storage_Offset)
          return Address;

Also assuming that you want exactly C's pointer arithmetic,
copying C's rules, relying on void* casts, and not use Ada
facilities for a reason. (Side note: C's pointer arithmetic
and alignment are not defining what's in the hardware, storage
elements are not defined in C WRT size etc; C refers to hardware
and compiler for further reading.  That's somewhat less so in
Ada.)

Then Interfaces.C.Pointers is your friend, for helping with writing
C in Ada, including the necessary C pointer arithmetic functions,
such as

	function "+" (Left : in Pointer;  Right : in ptrdiff_t)
	  return Pointer;

It is also worthwhile searching the compiler docs that state which
type corresponds with C's void* on your platform.  (System.Address
in case of many GNATs.)

If the platform allows direct interpretation of the bits of
a pointer as an Unsigned_N (no composite pointers, for example),
then after Unchecked_Conversion, the bit operations used in
align_ptr above would be those of Unsigned_N (with suitable N),
named "and" and "not".



^ permalink raw reply	[relevance 5%]

* Re: using `use' : what is the best practice ?
  @ 2011-06-08 19:22  4%     ` Pascal Obry
  0 siblings, 0 replies; 144+ results
From: Pascal Obry @ 2011-06-08 19:22 UTC (permalink / raw)


Le 08/06/2011 11:31, milouz a �crit :
> Yes, as I'm new to Ada, I still have a lot of things to learn /
> understand. I'm a kernel developer, and my way to learn Ada is to
> write some drivers and very low-level stuffs. That's why I need to
> play with address arithmetic.

Not sure what you are trying to do but maybe Interfaces.C.Pointers would 
fit your needs.

Pascal.

-- 

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|    http://www.obry.net  -  http://v2p.fr.eu.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver keys.gnupg.net --recv-key F949BD3B




^ permalink raw reply	[relevance 4%]

* Re: Fun with C
  @ 2011-04-20 21:09  4%       ` Georg Bauhaus
  0 siblings, 0 replies; 144+ results
From: Georg Bauhaus @ 2011-04-20 21:09 UTC (permalink / raw)


On 4/20/11 9:04 PM, Vinzent Hoefler wrote:

> <http://www.open-std.org/jtc1/sc22/wg14/www/charter>:
>
> |Some of the facets of the spirit of C can be summarized in phrases like
> |(a) Trust the programmer.
> |(b) Don't prevent the programmer from doing what needs to be done.
> |(c) Keep the language small and simple.
> |(d) Provide only one way to do an operation.
> |(e) Make it fast, even if it is not guaranteed to be portable.

Not much different from what is true about Ada.

(a) (Like Haskell,) Ada trusts the programmer to be explicit,
e.g. instantiating Unchecked_Conversion.
Normally, though, Ada doesn't trust us when we want to pass
addresses of local objects up the call chain. But it is possible.

(b) Ada seems to make it a little difficult to get pointer arithmetic
from Interfaces.C.Pointers to omit null tests.  But otherwise...

(c) The C standard is about the same size as Ada's, isn't it?
C is simple?

(d) Are there two ways to do an operation in Ada?

(e) Some Ada programs are fast and still guaranteed to be portable.
That's true of some C programs as well.  Ada programs might need unchecked
conversions and representation clauses to make a program non-portable.

Although, an Ada program need not be non-portable even though we let
the *compiler* choose efficient the representation on a target
machine:

     type Roman is ('M', 'D', 'C', 'L', 'V', 'I', 'X');
     for Roman'Size use Integer'Size;

     function To_Integer is new Unchecked_Conversion(Roman, Integer);

Now

     To_Integer(X) + N;

will produce the "byte operation [that] is more efficient on the
target machine" iff the compiler uses efficient byte operations
for Integer.  Or this,

     type S is new String;
     for S'Component_Size use Integer'Size;

So I guess C's (e) is working around the fact that C's choices
would not allow the programmer to say what needs to be done?




^ permalink raw reply	[relevance 4%]

* Re: Ada to C interfacing with access on unconstrained array
  2009-10-20 13:07  6% Ada to C interfacing with access on unconstrained array dhenry
@ 2009-10-20 16:24  0% ` Adam Beneschan
  0 siblings, 0 replies; 144+ results
From: Adam Beneschan @ 2009-10-20 16:24 UTC (permalink / raw)


On Oct 20, 6:07 am, dhenry <tfc.d...@gmail.com> wrote:
> Hello,
>
> I am trying to interface C with Ada: I want to call an Ada procedure
> from C.
> The Ada procedure takes as parameter a record, containing some
> integers and
> fat access types ("access all").
>
> Ideally, I'd like to have no copy during the interfacing between Ada
> and C.

David,

Unfortunately, I don't think there's a solution.  The reason is that
on some implementations, the Nut_Array_Access, which is an access to
an unconstrained array, is implemented by making sure that a vector
containing the bounds is adjacent to the array data, and having the
access type be the address of the array data or perhaps the address of
the bounds, or something like that.  That means that if you have an
area of memory consisting just of data array, with no bound vector
adjacent to it, you can't convert the location to an access-to-
unconstrained-array type without copying the data.

                                            -- Adam


> Here is the Ada code:
>
> --------------------------------------------------
> package Foo is
>
>    type Nut_Type is
>       record
>          Diameter : Integer;
>          Weight   : Integer;
>          Age      : Integer;
>       end record;
>
>    type Nut_Array_Type is array (Positive range <>) of Nut_Type;
>    type Nut_Array_Access is access Nut_Array_Type;
>
>    type Coco_Type is
>       record
>          X    : Integer;
>          Y    : Integer;
>          Nuts : Nut_Array_Access;
>       end record;
>
>    -- This is the procedure I want to be executed from C
>    procedure Climb (Coco : in Coco_Type);
>
> end Foo;
> --------------------------------------------------
> package body Foo is
>
>    procedure Climb (Coco : in Coco_Type) is
>    begin
>       -- Climb on the coco...
>    end Climb;
>
> end Foo;
> --------------------------------------------------
>
> I want to use the Climb procedure. For interfacing, I can create an
> intermediate
> procedure C_Climb that fits well with C, but the Climb procedure can't
> be changed.
>
> The C_Climb procedure will take some data from C, and rebuild a
> Coco_Type object
> to give to the Climb procedure: "C program" => C_Climb => Climb.
>
> My main problem is the Coco_Type.Nuts component, which is an access to
> an
> unconstrained array. I can't find how to map it without allocation/
> copy data.
>
> Here is an attempt to implement C_Climb:
>
> --------------------------------------------------
> with Interfaces.C;
> with Interfaces.C.Pointers;
>
> package Foo.C_Interface is
>
>    type C_Nut_Type is
>       record
>          Diameter : Interfaces.C.int;
>          Weight   : Interfaces.C.int;
>          Age      : Interfaces.C.int;
>       end record;
>
>    type C_Nut_Array is array (Interfaces.C.int range <>) of aliased
> C_Nut_Type;
>    type C_Nut_Array_Access is access all C_Nut_Array;
>
>    package C_Nut_Pointers is
>       new Interfaces.C.Pointers (Interfaces.C.int, C_Nut_Type,
> C_Nut_Array, (0, 0, 0));
>
>    procedure Climb_C (C_X    : in Interfaces.C.int;
>                       C_Y    : in Interfaces.C.int;
>                       C_Nuts : in C_Nut_Pointers.Pointer;
>                       C_Len  : in Interfaces.C.int);
>
>    pragma Export (C, Climb_C, "climb");
>
> end Foo.C_Interface;
> --------------------------------------------------
> package body Foo.C_Interface is
>
>    procedure Climb_C (C_X    : in Interfaces.C.int;
>                       C_Y    : in Interfaces.C.int;
>                       C_Nuts : in C_Nut_Pointers.Pointer;
>                       C_Len  : in Interfaces.C.int) is
>
>       subtype My_Nuts is C_Nut_Array (1 .. C_Len);
>       type My_Nuts_Access is access all My_Nuts;
>
>       Nuts : aliased My_Nuts;
>       for Nuts'Address use C_Nuts.all'Address;
>
>       Nuts_Ptr : My_Nuts_Access := Nuts'Unchecked_Access;
>
>       Coco : Coco_Type;
>    begin
>       Coco.X    := Integer (C_X);
>       Coco.Y    := Integer (C_Y);
>
>       -- How do I connect this access with my C pointer C_Nuts?
>       Coco.Nuts := Nuts_Ptr; -- FAIL because My_Nuts_Access is not an
> Nut_Array_Access
>
>       Climb (Coco);
>    end Climb_C;
>
> end Foo.C_Interface;
> --------------------------------------------------
>
> Currently, the only way I found is to declare a Nut_Array_Access and
> allocate memory with new:
>
> Nuts_Ptr : Nut_Array_Access := new Nut_Array_Type (1 .. Integer
> (C_Len));
>
> So I can write "Coco.Nuts := Nuts_Access;". But I must fill
> Nuts_Access.all with C_Nuts' data, and
> that's what I'd like to avoid.
>
> Any idea on the interfacing is welcome.
>
> Yours,
> David.




^ permalink raw reply	[relevance 0%]

* Ada to C interfacing with access on unconstrained array
@ 2009-10-20 13:07  6% dhenry
  2009-10-20 16:24  0% ` Adam Beneschan
  0 siblings, 1 reply; 144+ results
From: dhenry @ 2009-10-20 13:07 UTC (permalink / raw)


Hello,

I am trying to interface C with Ada: I want to call an Ada procedure
from C.
The Ada procedure takes as parameter a record, containing some
integers and
fat access types ("access all").

Ideally, I'd like to have no copy during the interfacing between Ada
and C.

Here is the Ada code:

--------------------------------------------------
package Foo is

   type Nut_Type is
      record
         Diameter : Integer;
         Weight   : Integer;
         Age      : Integer;
      end record;

   type Nut_Array_Type is array (Positive range <>) of Nut_Type;
   type Nut_Array_Access is access Nut_Array_Type;

   type Coco_Type is
      record
         X    : Integer;
         Y    : Integer;
         Nuts : Nut_Array_Access;
      end record;

   -- This is the procedure I want to be executed from C
   procedure Climb (Coco : in Coco_Type);

end Foo;
--------------------------------------------------
package body Foo is

   procedure Climb (Coco : in Coco_Type) is
   begin
      -- Climb on the coco...
   end Climb;

end Foo;
--------------------------------------------------

I want to use the Climb procedure. For interfacing, I can create an
intermediate
procedure C_Climb that fits well with C, but the Climb procedure can't
be changed.

The C_Climb procedure will take some data from C, and rebuild a
Coco_Type object
to give to the Climb procedure: "C program" => C_Climb => Climb.

My main problem is the Coco_Type.Nuts component, which is an access to
an
unconstrained array. I can't find how to map it without allocation/
copy data.

Here is an attempt to implement C_Climb:

--------------------------------------------------
with Interfaces.C;
with Interfaces.C.Pointers;

package Foo.C_Interface is

   type C_Nut_Type is
      record
         Diameter : Interfaces.C.int;
         Weight   : Interfaces.C.int;
         Age      : Interfaces.C.int;
      end record;

   type C_Nut_Array is array (Interfaces.C.int range <>) of aliased
C_Nut_Type;
   type C_Nut_Array_Access is access all C_Nut_Array;

   package C_Nut_Pointers is
      new Interfaces.C.Pointers (Interfaces.C.int, C_Nut_Type,
C_Nut_Array, (0, 0, 0));

   procedure Climb_C (C_X    : in Interfaces.C.int;
                      C_Y    : in Interfaces.C.int;
                      C_Nuts : in C_Nut_Pointers.Pointer;
                      C_Len  : in Interfaces.C.int);

   pragma Export (C, Climb_C, "climb");

end Foo.C_Interface;
--------------------------------------------------
package body Foo.C_Interface is

   procedure Climb_C (C_X    : in Interfaces.C.int;
                      C_Y    : in Interfaces.C.int;
                      C_Nuts : in C_Nut_Pointers.Pointer;
                      C_Len  : in Interfaces.C.int) is

      subtype My_Nuts is C_Nut_Array (1 .. C_Len);
      type My_Nuts_Access is access all My_Nuts;

      Nuts : aliased My_Nuts;
      for Nuts'Address use C_Nuts.all'Address;

      Nuts_Ptr : My_Nuts_Access := Nuts'Unchecked_Access;

      Coco : Coco_Type;
   begin
      Coco.X    := Integer (C_X);
      Coco.Y    := Integer (C_Y);

      -- How do I connect this access with my C pointer C_Nuts?
      Coco.Nuts := Nuts_Ptr; -- FAIL because My_Nuts_Access is not an
Nut_Array_Access

      Climb (Coco);
   end Climb_C;

end Foo.C_Interface;
--------------------------------------------------

Currently, the only way I found is to declare a Nut_Array_Access and
allocate memory with new:

Nuts_Ptr : Nut_Array_Access := new Nut_Array_Type (1 .. Integer
(C_Len));

So I can write "Coco.Nuts := Nuts_Access;". But I must fill
Nuts_Access.all with C_Nuts' data, and
that's what I'd like to avoid.

Any idea on the interfacing is welcome.

Yours,
David.



^ permalink raw reply	[relevance 6%]

* Re: calling ada from c with an array param
  @ 2009-09-21  8:04  6% ` Dmitry A. Kazakov
  0 siblings, 0 replies; 144+ results
From: Dmitry A. Kazakov @ 2009-09-21  8:04 UTC (permalink / raw)


On Sun, 20 Sep 2009 12:38:04 -0700 (PDT), Mike wrote:

> I'm new to Ada so I'm trying to expand a simple c example that passed
> primitive types to an Ada
> function. I'm trying to call an ada procedure from a c program with an
> in out float array using GNAT.

Your idea is in general OK, and a huge flat array could be used to
interface C. Alternatively there is Interfaces.C.Pointers package in the
standard library intended for this purpose. (Since C does not have arrays
you cannot pass them to Ada (:-))

In general when interfacing to C, your program shall use C types as
provided by the package Interfaces.C. For example, there is no warranty to
consider Ada's Float an equivalent to C's float.

> Obviously there is a problem declaring the array, but I'm not sure
> where it goes. Can someone help?

Here is a modified variant of your attempt:
-------------- main.c ----------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern void conjunc (float[], int);

int main (int argc, char *argv[])
{
   int i;
   float a[4] = {0.0, 0.0, 0.0, 0.0};

   conjunc(a, sizeof(a)/sizeof(float));

   for (i = 0; i <= 3; i++)
   {
     printf("a[%d] = %f ", i, a[i]);
   }
}

I will illustrate both approaches.

1. Interfaces.C.Pointers:

--------- conjunc.ads --------------------
with Interfaces.C;  use Interfaces.C;
with Interfaces.C.Pointers;

package conjunc is
   type C_Float_Array is array (int range <>) of aliased C_Float; -- Sic!
   package C_Float_Pointers is
      new Interfaces.C.Pointers (int, C_Float, C_Float_Array, 0.0);
   use C_Float_Pointers;
   procedure conj (A : Pointer; Len: int);
   pragma Export (C, conj, "conjunc");
end conjunc;
--------- conjunc.adb --------------------
package body conjunc is
   procedure conj (A : Pointer; Len: int) is
      Data : C_Float_Array (1..Len);
      for Data'Address use A.all'Address;
      pragma Import (Ada, Data); -- Not necessary here, but cleaner
   begin
      Data (1) := 99.0;
      Data (2) := 100.0;
      Data (3) := 101.0;
      Data (4) := 102.0;
   end conj;
end conjunc;
------------------------------------------
Note that C_Float_Array is an array of aliased C_Float. C_Float is declared
in Interfaces.C and must be same as C's float. To have it aliased is
required because in C you can get pointer to each "array" element, for
obvious reason of not having arrays. In Ada it is in general wrong because
an array can be packed. Within the body of conjunc the pointer passed from
C is mapped to a constrained array of specified length (Data). You can also
use pointer arithmetic as you would in C, but it would be to tedious. So I
just declared Data of desired length located where the pointer points.

To build this with GNAT, do:

gcc -c main.c
gnatmake -c conjunc.adb
gnatbind -n conjunc.ali
gnatlink conjunc.ali main.o -o main

2. Here is a variant based on flat arrays:
--------- conjunc.ads --------------------
with Interfaces.C;  use Interfaces.C;

package conjunc is
   type C_Float_Array is array (int range <>) of aliased C_Float;
   subtype Flat_C_Float_Array is C_Float_Array (1..int'Last);
   procedure conj (A : in out Flat_C_Float_Array; Len: int);
   pragma Export (C, conj, "conjunc");
end conjunc;
--------- conjunc.adb --------------------
package body conjunc is
   procedure conj (A : in out Flat_C_Float_Array; Len: int) is
   begin
      A (1) := 99.0;
      A (2) := 100.0;
      A (3) := 101.0;
      A (4) := 102.0;
   end conj;
end conjunc;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 6%]

* Re: Representing image data
  @ 2009-03-11 21:12  4%   ` Kenneth Almquist
  0 siblings, 0 replies; 144+ results
From: Kenneth Almquist @ 2009-03-11 21:12 UTC (permalink / raw)


Thanks for the responses.

> What sort of applications have you in mind?

Ideally, any application that uses raster image data.  The idea behind
row-at-a-time mode is that the application will read the data in each
row and store it in a format appropriate for the application.

The ability to read an entire image at once is based on the assumption
that the result will in a useable format for a lot of applications,
but that may be more true in C, where we are concerned with binary
compatibility rather than logical compatibility between types.

> There are various libraries, full Ada (at least for BMP, GIF, TGA & PPM) 
> or bindings, which support these usual formats.

I found ImageMagick, which Srini mentioned, and found two more libraries
listed on www.adapower.com.  Any suggestions of where else to look?

With ImageMagick the only way to change the pixel format is to
recompile the library, so the interface doesn't have to deal with
multiple pixel formats.  It uses Interfaces.C.Pointers to enable the
interface to return a pointer to an array of pixels; a solution that
the documentation acknowledges isn't very good.

PNG-IO, which reads PNG files, has functions to access the sample values:

    function Pixel_Value(F : PNG_File; R, C : Coordinate) return Natural;
    function   Red_Value(F : PNG_File; R, C : Coordinate) return Natural;
    function Green_Value(F : PNG_File; R, C : Coordinate) return Natural;
    function  Blue_Value(F : PNG_File; R, C : Coordinate) return Natural;
    function Alpha_Value(F : PNG_File; R, C : Coordinate) return Natural;

These functions are inlined, but require a fair amount of computation
because their behavior depends on the attributes of the image, which
have to be checked every call.

Open-image has declarations for the various pixel types, which seems
to be a workable approach, but I have to think about it some more.

			    Kenneth Almquist



^ permalink raw reply	[relevance 4%]

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14 11:16  4%     ` Dmitry A. Kazakov
@ 2009-02-14 11:37  0%       ` xorquewasp
  0 siblings, 0 replies; 144+ results
From: xorquewasp @ 2009-02-14 11:37 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> On Sat, 14 Feb 2009 02:38:35 -0800 (PST), xorquewasp@googlemail.com wrote:
> > That does mean going outside of the RM, which is a bit unfortunate.
> > I'll keep it in mind, however.
>
> What do you mean by that? Interfaces.C.Pointers is a part of the standard
> Ada library.

Sorry, I was thinking of Interfaces.C.Extensions.

> One technique is to declare a huge flat array:
>

Thanks for that. I'll try it.



^ permalink raw reply	[relevance 0%]

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14 10:38  0%   ` xorquewasp
@ 2009-02-14 11:16  4%     ` Dmitry A. Kazakov
  2009-02-14 11:37  0%       ` xorquewasp
  0 siblings, 1 reply; 144+ results
From: Dmitry A. Kazakov @ 2009-02-14 11:16 UTC (permalink / raw)


On Sat, 14 Feb 2009 02:38:35 -0800 (PST), xorquewasp@googlemail.com wrote:

> Dmitry A. Kazakov wrote:
>>
>> I would suggest to use Interfaces.C.Pointers instead of
>> Interfaces.C.Strings:
> 
> That does mean going outside of the RM, which is a bit unfortunate.
> I'll keep it in mind, however.

What do you mean by that? Interfaces.C.Pointers is a part of the standard
Ada library.

>> Are you sure that get_data is char **, int * rather than void **, size_t *?
>> In the latter case I would consider Storage_Array instead of String on the
>> Ada side.
> 
> Well, the C function parameters are defined as char **, int * but do have
> a meaning closer to void **, size_t *. Storage_Array is probably more
> appropriate, as you state. That still leaves the question of
> converting from an address or access type to an unconstrained array (can't pass an
> unconstrained array or access to an unconstrained array to C code).

One technique is to declare a huge flat array:

   type Never_Instantiate_Me is array (size_t'range) of char;
   pragma Convention (C, Never_Instantiate_Me);

or else simply:

   subtype Never_Instantiate_Me is char_array (size_t'range);

Never_Instantiate_Me will have no dope.

   type Never_Instantiate_Me_Ptr is access all Never_Instantiate_Me;
   pragma Convention (C, Never_Instantiate_Me_Ptr);;

Then you go:

   function Get return String is
      procedure memory_data
                (  data   : out Never_Instantiate_Me_Ptr;
                   size   : out size_t
                );
      pragma Import (C, memory_data, "get_data");
      Data : Never_Instantiate_Me_Ptr;
      Size : size_t;
   begin
      memory_data (Data, Size);
      if Size = 0 then
         return "";
      else
         return
            To_Ada
            (  Data (size_t'First..size_t'First + Size - 1),
               False
            );
      end if;
   end Get;

Note Size = 0 check. When Size is zero, there is no way to construct an
empty char_array since size_t is modular.
 
-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 4%]

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  2009-02-14  9:26  6% ` Dmitry A. Kazakov
@ 2009-02-14 10:38  0%   ` xorquewasp
  2009-02-14 11:16  4%     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 144+ results
From: xorquewasp @ 2009-02-14 10:38 UTC (permalink / raw)




Dmitry A. Kazakov wrote:
>
> I would suggest to use Interfaces.C.Pointers instead of
> Interfaces.C.Strings:
>

That does mean going outside of the RM, which is a bit unfortunate.
I'll keep it in mind, however.

>
> Are you sure that get_data is char **, int * rather than void **, size_t *?
> In the latter case I would consider Storage_Array instead of String on the
> Ada side.

Well, the C function parameters are defined as char **, int * but do
have
a meaning closer to void **, size_t *. Storage_Array is probably more
appropriate, as you state. That still leaves the question of
converting from
an address or access type to an unconstrained array (can't pass an
unconstrained array or access to an unconstrained array to C code).

>
> Yet another issue. It is not so frequent that C API allocated a data buffer
> and returned it to the caller, as your example suggests.

In this case, the library remains in complete control of the memory.

(It's one of the OpenSSL bio.h functions, if anyone's really curious).



^ permalink raw reply	[relevance 0%]

* Re: Converting pointers to non nul-terminated C "strings" to Ada string
  @ 2009-02-14  9:26  6% ` Dmitry A. Kazakov
  2009-02-14 10:38  0%   ` xorquewasp
  0 siblings, 1 reply; 144+ results
From: Dmitry A. Kazakov @ 2009-02-14  9:26 UTC (permalink / raw)


On Fri, 13 Feb 2009 22:58:55 -0800 (PST), xorquewasp@googlemail.com wrote:

> I have some C code that returns a pointer to a buffer of
> "data" (not a string, just raw data) and also returns the
> size of the buffer:
> 
> void
> get_data (char **ptr, int *size);
> 
> int size;
> char *ptr;
> 
> get_data (&ptr, &size);
> 
> The code is part of a library that I don't control, so I can't
> change the interface.
> 
> I've defined the Ada equivalent as:
> 
>     package CS renames Interfaces.C.Strings;
>     package C renames Interfaces.C;
> 
>     procedure memory_data
>       (data   : out CS.chars_ptr;
>        size   : out C.int);
>     pragma Import (C, memory_data, "get_data");
> 
> This works correctly, however I'm having trouble converting
> the chars_ptr type to an Ada string given that it's not nul-
> terminated.
> 
> Attempts to do the following:
> 
> return CS.Value (Item => data, Length => size);
> 
> ... results in a String as long as the position of the first nul in
> the
> C string (the position is inevitably less than the length of the
> string).
> 
> Is it possible to properly convert unterminated C strings or do I
> need to start messing about with raw System.Address types?

I would suggest to use Interfaces.C.Pointers instead of
Interfaces.C.Strings:

with Interfaces.C;           use Interfaces.C;
with Interfaces.C.Pointers;

package Char_Ptrs is
   new Interfaces.C.Pointers (size_t, char, char_array, Nul);
use Char_Ptrs;

function Get return String is
   procedure memory_data
             (  data   : out Pointer;
                size   : out ptrdiff_t  -- Really int as in your example?
             );
   pragma Import (C, memory_data, "get_data");
   Data : Pointer;
   Size : ptrdiff_t;
begin
   memory_data (Data, Size);
   return To_Ada (Value (Data, Size), False);
end Get;

Are you sure that get_data is char **, int * rather than void **, size_t *?
In the latter case I would consider Storage_Array instead of String on the
Ada side.

Yet another issue. It is not so frequent that C API allocated a data buffer
and returned it to the caller, as your example suggests. Usually it is the
caller who passes an array to the C callee specifying its maximal capacity.
In this case the code should be different. In the former case, the question
arise, who is responsible for feeing the buffer. Does Data point to some
statically allocated piece of memory inside C library, or else you have to
free Data after converting it to Ada array?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 6%]

* Re: A curiosity...
  @ 2008-12-05  9:03  4%       ` Georg Bauhaus
  0 siblings, 0 replies; 144+ results
From: Georg Bauhaus @ 2008-12-05  9:03 UTC (permalink / raw)


Ludovic Brenta wrote:

> Yes. In fact, C requires that pointers and integers be interchangable
> so as to make address arithmetic "transparent" and extremely
> dangerous.

Uhm, not interchangeable has been pointed out; this also seems
to be reflected in how Interfaces.C.Pointers is made. To me, a more
significant difference is that we do have more predefined mechanism
around Ada arrays. th + 100 is defined in C, it needs
not designate an element of an allocated array, though
(being off bounds, off the intended cell, whatever ...).
and this is not checked. You get erroneous execution,
or some kind of violation will kill the program if 100 happens
to be too much.  (C programmers might feel that they are
more skilled when they do not rely on what they might call a cane:
array bounds checking at run time, as is done in Ada and
in C++/STL (with .at)... "The C language is alright, just pick
real programmers!" is what I have heard now and then.)

When you implement an Ada storage pool, can you rely
on an Ada array to be mapped linearly to the sequence
of hardware addresses?  Is this important?



^ permalink raw reply	[relevance 4%]

* Re: Adding offset to 'Address
  2008-09-12 10:17  0%   ` Kim Rostgaard Christensen
@ 2008-09-12 11:18  0%     ` petter_fryklund
  0 siblings, 0 replies; 144+ results
From: petter_fryklund @ 2008-09-12 11:18 UTC (permalink / raw)


On 12 Sep, 12:17, Kim Rostgaard Christensen <k...@greenpc.dk> wrote:
> Georg Bauhaus wrote:
> > Kim Rostgaard Christensen wrote:
> >> Hi
>
> >> How does one go about setting a 'Address + (size of other record) to a
> >> record at runtime ?
>
> > Have you had a chance to look at Interfaces.C.Pointers?
>
> > -- Georg Bauhaus
>
> I have thought about it, yes - but I cannot figure out witch datatype I
> should instantiate my pointer with (other than Byte & Byte_Array).
>
> Can you give an example ?
>
> regards
> Kim Rostgaard Christensen

System.Storage_Elements can be useful for arithmetic on 'Address.



^ permalink raw reply	[relevance 0%]

* Re: Adding offset to 'Address
  2008-09-12  9:47  4% ` Georg Bauhaus
@ 2008-09-12 10:17  0%   ` Kim Rostgaard Christensen
  2008-09-12 11:18  0%     ` petter_fryklund
  0 siblings, 1 reply; 144+ results
From: Kim Rostgaard Christensen @ 2008-09-12 10:17 UTC (permalink / raw)


Georg Bauhaus wrote:
> Kim Rostgaard Christensen wrote:
>> Hi
>>
>> How does one go about setting a 'Address + (size of other record) to a
>> record at runtime ?
> 
> Have you had a chance to look at Interfaces.C.Pointers?
> 
> 
> -- Georg Bauhaus
> 
I have thought about it, yes - but I cannot figure out witch datatype I 
should instantiate my pointer with (other than Byte & Byte_Array).

Can you give an example ?

regards
Kim Rostgaard Christensen



^ permalink raw reply	[relevance 0%]

* Re: Adding offset to 'Address
  @ 2008-09-12  9:47  4% ` Georg Bauhaus
  2008-09-12 10:17  0%   ` Kim Rostgaard Christensen
  0 siblings, 1 reply; 144+ results
From: Georg Bauhaus @ 2008-09-12  9:47 UTC (permalink / raw)


Kim Rostgaard Christensen wrote:
> Hi
> 
> How does one go about setting a 'Address + (size of other record) to a
> record at runtime ?

Have you had a chance to look at Interfaces.C.Pointers?


-- Georg Bauhaus




^ permalink raw reply	[relevance 4%]

* Re: Possible compiler bug with this simple program
  @ 2008-09-04 14:42  5%                       ` Jacob Sparre Andersen
  0 siblings, 0 replies; 144+ results
From: Jacob Sparre Andersen @ 2008-09-04 14:42 UTC (permalink / raw)


[ calling an Ada function from C with an array argument ]

Isn't this a case, where package Interfaces.C.Pointers is appropriate
to use?  (Despite the name, it seems mostly to be concerned with
C-style "arrays".)

Greetings,

Jacob
-- 
"Never trust a statistic you have not falsified yourself."



^ permalink raw reply	[relevance 5%]

* Re: Ada array vs C pointer (call by reference)
  @ 2008-06-28  1:21  6% ` anon
  0 siblings, 0 replies; 144+ results
From: anon @ 2008-06-28  1:21 UTC (permalink / raw)


The unsafe way is to use "Address" attribute.

   function pwmRead ( Count : Interfaces.C.int ;
                      Data  : System.Address ) return Interfaces.C.int ;
   pragma Import ( C, pwmRead, "pwmRead" ) ;


The standard safe method you must use two interface packages.

   Interfaces.C ;
   Interfaces.C.Pointers ;

and create a C type of pointer package for the Float type, such as

   type Float_array is array ( Interfaces.C.size_t range <> ) 
        of aliased float;

    package Float_Pointer is new 
        Interfaces.C.Pointers ( Index              => size_t,
                                Element            => Float,
                                Element_Array      => Float_array,
                                Default_Terminator => 0 ) ;


study RM B.3.2 ( 45 ) for an example that uses character array. Should 
be easy to adapt to Float.


In <d390ae47-83b1-4cfb-8e66-d6a92f38cf4e@z32g2000prh.googlegroups.com>, Adrian Hoe <abyhoe@gmail.com> writes:
>Hi,
>
>I have a C library function which takes a float * as a parameter. The
>function is as below:
>
>   int pwmRead (int pwmCount, float * data);
>
>where data is an array of float which size is determined by pwmCount.
>
>In Ada, I have:
>
>   PWM_Count : Integer := No_Of_Components_Intended;
>   PWM_Data : array (1 .. PWM_Count) of Float;
>
>My concern is how safe to pass an Ada array to a C function as a
>pointer (call by reference)? I presume Ada will allocate contiguous
>memory for array, but what if it does not? How can we establish a
>deterministic allocation and to make sure float * is accessed
>contiguously? Is there any "safe" way to do this?
>
>Thanks.
>--
>Adrian Hoe
>http://adrianhoe.com




^ permalink raw reply	[relevance 6%]

* Re: Pointer
  2008-05-19 12:09  6%         ` Pointer Dmitry A. Kazakov
@ 2008-05-19 12:47  0%           ` Sébastien
  0 siblings, 0 replies; 144+ results
From: Sébastien @ 2008-05-19 12:47 UTC (permalink / raw)


> with Interfaces.C.Pointers;
> with Interfaces.C.Strings;  use Interfaces.C.Strings;
> with Interfaces.C; use Interfaces.C;
> 
> type Chars_Ptr_Array is array (size_t range <>) of aliased chars_ptr;
> pragma Convention (C, Chars_Ptr_Array);
> package Pointers_To_String is
>    new Interfaces.C.Pointers (size_t, chars_ptr, chars_ptr_array, null);
> use Pointers_To_String;
> ...   
> Data : Pointers_To_String.Pointer := MyCFunctionReturninCharStarStar;
> N: Natural := MYCFunctionTellingMeHowManyStrings;
> ...
> for Index in 1..N loop
>    declare
>       Element : String := Value (Data.all);
>    begin
>       ... -- Use the element
>    end;
>    Increment (Data); -- Move to the next one
> end loop;

Ok I didn't know Interfaces.C.Pointer, it's looks like exaclty what I 
need and it's a replacement for pointer arithmetic operations.



^ permalink raw reply	[relevance 0%]

* Re: Pointer
  @ 2008-05-19 12:09  6%         ` Dmitry A. Kazakov
  2008-05-19 12:47  0%           ` Pointer Sébastien
  0 siblings, 1 reply; 144+ results
From: Dmitry A. Kazakov @ 2008-05-19 12:09 UTC (permalink / raw)


On Mon, 19 May 2008 11:31:57 +0000, S�bastien wrote:

>> procedure To_String (Pointer : in System.Address; Length : in Natural)
>> return String is
>>    Result : String (1 .. Length);
>>    for Result'Address use Pointer;
>>    pragma Import (Ada, Result); -- suppress default initialization
>> begin
>>    return Result;
>> end To_String;
>> 
>> But Dmitryi's solution is safer, of course. HTH
> 
> Ok, I was not clear enough. Converting char* to String is not an issue, 
> I'm using Interfaces.C.String with no problem. My problem is to convert 
> all the strings in the char** in string one by one.

Aha, it is const char *[] ...

> Something like this:
> CharPtrPtr: System.Address := MyCFunctionReturninCharStarStar;
> N: Natural := MYCFunctionTellingMeHowManyStrings;
> 
> for i in Natural range 0 .. N loop
>     -- Some ada code to convert CharPtrPtr[i] to String
> end loop;

with Interfaces.C.Pointers;
with Interfaces.C.Strings;  use Interfaces.C.Strings;
with Interfaces.C; use Interfaces.C;

type Chars_Ptr_Array is array (size_t range <>) of aliased chars_ptr;
pragma Convention (C, Chars_Ptr_Array);
package Pointers_To_String is
   new Interfaces.C.Pointers (size_t, chars_ptr, chars_ptr_array, null);
use Pointers_To_String;
...   
Data : Pointers_To_String.Pointer := MyCFunctionReturninCharStarStar;
N: Natural := MYCFunctionTellingMeHowManyStrings;
...
for Index in 1..N loop
   declare
      Element : String := Value (Data.all);
   begin
      ... -- Use the element
   end;
   Increment (Data); -- Move to the next one
end loop;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 6%]

* Re: Variable list parameters
  @ 2007-11-28  8:48  6%     ` axtens
  0 siblings, 0 replies; 144+ results
From: axtens @ 2007-11-28  8:48 UTC (permalink / raw)


Newbie says, "What about Stdarg.Impl?"

-- $Source: /user/cp_source/ObjectAda/rts/bindings/win32ada/stdarg/
impl.ads,v $
-- $Revision: 1.1 $ $Date: 2001/01/09 19:05:19 $ $Author: shancher $

with Interfaces.C.Pointers;

package Stdarg.Impl is

    -- *******************************************************
    -- Getting arguments out of lists, for use by implementers
    -- of variable-parameter functions
    -- *******************************************************

    subtype Int is Interfaces.C.Int;

    type Param_Access is private;

    function Address_of_First_Arg (Args: ArgList) return Param_Access;

    function Address_of_Vararg_List (Args: ArgList) return
Param_Access;

    function ArgCount (Args: ArgList) return Int;

    function "&" (Left, Right: ArgList) return ArgList;

    procedure Do_Varargs (Proc     : in System.Address;
                          Nb_Args  : Int;
                          Arg_Addr : Param_Access);

    function F_Varargs (Func     : in System.Address;
                        Nb_Args  : Int;
                        Arg_Addr : Param_Access) return
Stdarg.C_Param;

    -- debugging
    -- procedure Dump(Addr: Param_Access; Nb_Args  : Stdarg.Int);
    -- pragma Import(C, Dump, "dump");

private

    package Arith is new Interfaces.C.Pointers(
	Integer, C_Param, Stdarg.ArgVector, 0);

    type Param_Access is new Arith.Pointer;

    pragma Import(C, Do_Varargs, "do_varargs");
    pragma Import(C, F_Varargs, "do_varargs");

-------------------------------------------------------------------------------
--
-- THIS FILE AND ANY ASSOCIATED DOCUMENTATION IS FURNISHED "AS IS"
WITHOUT
-- WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED
-- TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR
-- PURPOSE.  The user assumes the entire risk as to the accuracy and
the
-- use of this file.
--
-- Copyright (c) Intermetrics, Inc. 1995
-- Royalty-free, unlimited, worldwide, non-exclusive use,
modification,
-- reproduction and further distribution of this file is permitted.
--
-------------------------------------------------------------------------------


end Stdarg.Impl;


Kind regards,
Bruce.



^ permalink raw reply	[relevance 6%]

* Re: How to use Annex G.3 Vectors and Matrices in bindings to C arrays
  2006-11-13 11:20  4%   ` Jerry
@ 2006-11-13 19:09  0%     ` Jeffrey R. Carter
  0 siblings, 0 replies; 144+ results
From: Jeffrey R. Carter @ 2006-11-13 19:09 UTC (permalink / raw)


Jerry wrote:
>>
> I'm afraid I'll have to apologize for not being accurate in my initial
> post. Indeed, I am not having any problems (as I erroneously claimed)
> with 1D arrays. The problem arises with 2D arrays, about which I
> pestered the list earlier. With further apologies for posting a bit
> more code that I would like, the following is a typical binding that I
> made in which it was necessary to gain access to 2D C arrays.

OK.

>     z              : in out Long_Float_Array_2D; -- height of surface
> at definition points

I don't see why this is in out.

>     package PL_Float_Pointers_Local is new Interfaces.C.Pointers
>        (Index              => Integer,
>         Element            => Long_Float,
>         Element_Array      => Long_Float_Array_1D,
>         Default_Terminator => 0.0);
>     use type PL_Float_Pointers_Local.Pointer; -- as in RM B.3.2
>     type PL_Float_Pointer_Array_Local is array (Integer range <>) of
> PL_Float_Pointers_Local.Pointer; -- array of pointers to Long_Floats
> which represent the first element of each row of z in C-land
> 
>     Index_Of_First_Column : Integer := z'First(2);
>     z_As_Pointers : PL_Float_Pointer_Array_Local (z'range(1));
> 
>     procedure
>     plmeshc_local(x : PL_Float_Array; y : PL_Float_Array; z :
> PL_Float_Pointer_Array_Local; nx : Integer; ny : Integer; opt :
> Integer; clevel : PL_Float_Array; nlevel : PLINT);
>     pragma Import(C, plmeshc_local, "c_plmeshc");
> 
> begin
>     for Index in z'range(1) loop
>         z_As_Pointers(Index) := z(Index, Index_Of_First_Column)'access;

To do this, Z must have aliased components. If you want to use the 
language-defined matrix type for this, you'll have to copy the values 
from Z into a local array. I'd probably do something like

type Row_Of_Z is new Vector (Z'range (2) );
pragma Convention (C, Row_Of_Z);

type Row_Ptr is access all Row_Of_Z;
pragma Convention (C, Row_Ptr);

type Z_For_C is array (Z'range (1) ) of Row_Ptr;
pragma Convention (C, Z_For_C);

Z_Ptr : Z_For_C;

for I in Z_Ptr'range loop
    Z_Ptr := new Row_Of_Z;

    for J in Z'Ptr (I)'range loop
       Z_Ptr (J) := Z (I, J);
    end loop;
end loop;

-- Call C with Z_Ptr
-- Free Z_Ptr

You could, of course, put the rows into an array of aliased Row_Of_Z and 
use the 'access of its elements to fill Z_Ptr. That would eliminate the 
need to free the pointers.

A messy way, that doesn't involve copying the elements, is to 
instantiate System.Address_To_Access_Conversions, and derive a 
convention-C access type from the access type defined in the 
instantiation. Then you take 'Address, convert it to an access type 
using To_Pointer, then convert that to your convention-C access type and 
store it in your array of pointers. (This is equivalent to using GNAT's 
'Unrestricted_Access, but portable.)

> The related array definitions are:
>     type Long_Float_Array_1D is array (Integer range <>) of aliased
> Long_Float;
>     type Long_Float_Array_2D is array (Integer range <>, Integer range
> <>) of aliased Long_Float;
> 
> The "thin" binding Ada procedure plmeshc is defined:
>     procedure plmeshc(x : PL_Float_Array; y : PL_Float_Array; z :
> PL_Float_Array_2D; nx : PLINT; ny : PLINT; opt : PLINT;
>           clevel : PL_Float_Array; nlevel : PLINT);
>     pragma Import(C, plmeshc, "c_plmeshc");

The declarations of the PL_... types would be useful, too, though we can 
make a good guess from the C.

-- 
Jeff Carter
"Now go away or I shall taunt you a second time."
Monty Python & the Holy Grail
07



^ permalink raw reply	[relevance 0%]

* Re: How to use Annex G.3 Vectors and Matrices in bindings to C arrays
  @ 2006-11-13 11:20  4%   ` Jerry
  2006-11-13 19:09  0%     ` Jeffrey R. Carter
  0 siblings, 1 reply; 144+ results
From: Jerry @ 2006-11-13 11:20 UTC (permalink / raw)


Jeffrey R. Carter wrote:
> Jerry wrote:
> >
> > I wonder if I am incorrect in believing that the binding to C-arrays
> > need aliased components. Like I said, the reason for that is a little
> > fuzzy to me right now. But I do know that if I remove the aliased
> > component requirement from Long_Float_Array_1D the binding will not
> > compile.
>
> What is the error message that you get? Are you taking 'access of
> components of such arrays?
>
I'm afraid I'll have to apologize for not being accurate in my initial
post. Indeed, I am not having any problems (as I erroneously claimed)
with 1D arrays. The problem arises with 2D arrays, about which I
pestered the list earlier. With further apologies for posting a bit
more code that I would like, the following is a typical binding that I
made in which it was necessary to gain access to 2D C arrays.



procedure Mesh_3D_Base_Contour
   (x, y           : Long_Float_Array_1D; -- surface definition points
    z              : in out Long_Float_Array_2D; -- height of surface
at definition points
    Options        : Integer;
    Contour_Levels : Long_Float_Array_1D) is -- levels at which to draw
contours

    package PL_Float_Pointers_Local is new Interfaces.C.Pointers
       (Index              => Integer,
        Element            => Long_Float,
        Element_Array      => Long_Float_Array_1D,
        Default_Terminator => 0.0);
    use type PL_Float_Pointers_Local.Pointer; -- as in RM B.3.2
    type PL_Float_Pointer_Array_Local is array (Integer range <>) of
PL_Float_Pointers_Local.Pointer; -- array of pointers to Long_Floats
which represent the first element of each row of z in C-land

    Index_Of_First_Column : Integer := z'First(2);
    z_As_Pointers : PL_Float_Pointer_Array_Local (z'range(1));

    procedure
    plmeshc_local(x : PL_Float_Array; y : PL_Float_Array; z :
PL_Float_Pointer_Array_Local; nx : Integer; ny : Integer; opt :
Integer; clevel : PL_Float_Array; nlevel : PLINT);
    pragma Import(C, plmeshc_local, "c_plmeshc");

begin
    for Index in z'range(1) loop
        z_As_Pointers(Index) := z(Index, Index_Of_First_Column)'access;
    end loop;
    plmeshc_local(x, y, z_As_Pointers, x'Length, y'Length, Options,
Contour_Levels, Contour_Levels'Length); -- pass z_As_Pointers here
rather than z
end Mesh_3D_Base_Contour;



The related array definitions are:
    type Long_Float_Array_1D is array (Integer range <>) of aliased
Long_Float;
    type Long_Float_Array_2D is array (Integer range <>, Integer range
<>) of aliased Long_Float;

The "thin" binding Ada procedure plmeshc is defined:
    procedure plmeshc(x : PL_Float_Array; y : PL_Float_Array; z :
PL_Float_Array_2D; nx : PLINT; ny : PLINT; opt : PLINT;
          clevel : PL_Float_Array; nlevel : PLINT);
    pragma Import(C, plmeshc, "c_plmeshc");


And the original C procedure is defined as here:

http://plplot.sourceforge.net/docbook-manual/plplot-html-5.6.1/plmeshc.html

So it appears that I need to use access variables to mimic the 2D C
arrays, but the Annex G.3 Matrix definitions do not have aliased
elements. So, if you re-read my original post and substitute "2D" for
"1D" my original questions still stand.

Jerry




^ permalink raw reply	[relevance 4%]

* Re: How to pass two dimensional arrays to C
    2006-07-28 12:27  7% ` Dmitry A. Kazakov
  2006-08-02  8:20  6% ` Jerry
@ 2006-08-05  1:03  5% ` Jerry
  2 siblings, 0 replies; 144+ results
From: Jerry @ 2006-08-05  1:03 UTC (permalink / raw)


I want to close off this thread for the record.

Many thanks to everyone who helped me.

I have a working solution, pasted in sketch form below.

My only complaint with this solution is that I wanted to keep the thin
bindings, PlplotThin.ads, available and as a complete binding to anyone
who prefers it, if for no other reason than it is notationally closer
to the documentation (and _was_ essentially complete while the thick
binding will be finished only as my spare time permits). With this
solution, any PLplot subprogram which takes a two-dimensional array is
no longer accessible from the thin binding.

Maybe someday I'll learn enough Ada to find a way around this, but for
now, this works:


=============== my_common.ads
package My_Common is
    type Long_Float_Array_1D is array (Integer range <>) of aliased
Long_Float;
    type Long_Float_Array_2D is array (Integer range <>, integer range
<>) of aliased Long_Float;
end My_Common;



=============== plplotthin.ads
with
    My_Common;

package PLplotThin is
    subtype PLINT  is Integer;
    subtype PLFLT  is Long_Float;
    subtype PL_Float_Array    is My_Common.Long_Float_Array_1D;
    subtype PL_Float_Array_2D is My_Common.Long_Float_Array_2D;

    -- procedure plmesh is not defined in this package, but
	-- but in the thick binding PLplot wrapped in Mesh_3D.
	-- The same applies for the various other 3D plotters such
	-- as plmeshc, plot3d, plot3dc, and others which take a
	-- two-dimensional array as a parameter.
	-- These routines are unavailable from this thin binding.
end PLplotThin;


=============== plplot.adb
with
    PLplotThin,
    My_Common,
    Interfaces.C.Pointers,
    Interfaces.C;
use
    PLplotThin,
    My_Common,
    Interfaces.C;

package body PLplot is

    procedure Mesh_3D
       (x, y    : Long_Float_Array_1D; -- surface definition points
        z       : in out Long_Float_Array_2D; -- height of surface at
definition points
        Options : Integer) is

        package PL_Float_Pointers_Local is new Interfaces.C.Pointers
           (Index              => Integer,
            Element            => Long_Float,
            Element_Array      => Long_Float_Array_1D,
            Default_Terminator => 0.0);
        use type PL_Float_Pointers_Local.Pointer; -- as in RM B.3.2
        type PL_Float_Pointer_Array_Local is array (Integer range <>)
of PL_Float_Pointers_Local.Pointer; -- array of pointers to Long_Floats
which represent the first element of each row of z in C-land

        Index_Of_First_Column : Integer := z'First(2);
        z_As_Pointers : PL_Float_Pointer_Array_Local (z'range(1));

        procedure
        plmesh_local(x : PL_Float_Array; y : PL_Float_Array; z :
PL_Float_Pointer_Array_Local; nx : Integer; ny : Integer; opt :
Integer);
        pragma Import(C, plmesh_local, "c_plmesh");

    begin
        for Index in z'range(1) loop
            z_As_Pointers(Index) := z(Index,
Index_Of_First_Column)'access;
        end loop;
        plmesh_local(x, y, z_As_Pointers, x'Length, y'Length, Options);
-- pass z_As_Pointers here rather than z
    end Mesh_3D;

end PLplot;


=============== Testing_Thick_Binding.adb
with
    PlplotThin,
    PLplot,
    My_Common;
use
    PlplotThin,
    PLplot,
    My_Common;

package body Testing_Thick_Binding is
    procedure Main_Testing_Thick_Binding is
        z : aliased Long_Float_Array_2D (1..xpts, 1..ypts);
        pragma Convention(C, z); -- for compatibility with non-GNAT
        x : Long_Float_Array_1D (1..xpts);
        pragma Convention(C, x); -- for compatibility with non-GNAT
        y : Long_Float_Array_1D (1..ypts);
        pragma Convention(C, y); -- for compatibility with non-GNAT
    begin -- Main_Testing_Thick_Binding
		-- ...
		-- Calculate x, y, z.
		-- etc.
		-- ...
       	Mesh_3D(x, y, z, Options); -- call plmesh wrapper
		-- Clean up.
	end Main_Testing_Thick_Binding;
end Testing_Thick_Binding;




^ permalink raw reply	[relevance 5%]

* Re: How to pass two dimensional arrays to C
  2006-08-02  8:20  6% ` Jerry
  2006-08-02  9:03  0%   ` Dmitry A. Kazakov
@ 2006-08-02 18:25  0%   ` Björn Persson
  1 sibling, 0 replies; 144+ results
From: Björn Persson @ 2006-08-02 18:25 UTC (permalink / raw)


Jerry wrote:
> That kinda made sense to me, so I moved the declaration of the package
> PLFLT_Pointers is new Interfaces.C.Pointers along with its two
> associated subtype and type declarations inside the scope of procedure
> Mesh_3D, where you can see it commented-out above. With this
> uncommented and the similar declarations in plplotthin.ads
> commented-out, I get the compile error "plplotthin.ads:1025:56:
> "PLFLT_Ptr_Array" is undefined." Duh.
> 
> So how do I fix this conundrum?

Moving the declaration of plmesh into Mesh_3D isn't an option?

-- 
Bj�rn Persson                              PGP key A88682FD
                    omb jor ers @sv ge.
                    r o.b n.p son eri nu



^ permalink raw reply	[relevance 0%]

* Re: How to pass two dimensional arrays to C
  2006-08-02  9:03  0%   ` Dmitry A. Kazakov
@ 2006-08-02 10:22  0%     ` Jerry
  0 siblings, 0 replies; 144+ results
From: Jerry @ 2006-08-02 10:22 UTC (permalink / raw)



Dmitry A. Kazakov wrote:
> On 2 Aug 2006 01:20:34 -0700, Jerry wrote:
>
> > =============== my_common.ads
> > package My_Common is
> >     type Long_Float_Array_1D is array (Integer range <>) of aliased
> > Long_Float;
> >     type Long_Float_Array_2D is array (Integer range <>, integer range
> > <>) of aliased Long_Float;
>
> You cannot be sure that Integer is Interfaces.C.Int and Long_Float is
> Interfaces.C.Double.

My understanding is that with GNAT, these equivalences are guaranteed.
I know that what I've done is bad practice for portability, but I don't
think that it is the source of my problems. Please correct me if I am
wrong. However, I'll double-check this.

>
> > end My_Common;
> >
> > =============== plplotthin.ads
> > with
> >     Interfaces.C,
> >     Interfaces.C.Pointers,
> >     My_Common;
> > use
> >     Interfaces.C,
> >     Ada.Text_IO;
> >
> > package PLplotThin is
> >     subtype PLINT  is Integer;
> >     subtype PLFLT  is Long_Float;
>
> Same as above.
>
> >     subtype PL_Float_Array    is My_Common.Long_Float_Array_1D;
> >     subtype PL_Float_Array_2D is My_Common.Long_Float_Array_2D;
> >
> >     package PLFLT_Pointers is new Interfaces.C.Pointers
> >        (Index              => PLINT,
> >         Element            => PLFLT,
> >         Element_Array      => PL_Float_Array, -- was PLFLT_Array
> >         Default_Terminator => 0.0);
> >     subtype PLFLT_Ptr is PLFLT_Pointers.Pointer;
> >     type PLFLT_Ptr_Array is array (PLINT range <>) of aliased
> > PLFLT_Ptr;
> >
> >     procedure plmesh(
> > 		x   : PL_Float_Array;
> > 		y   : PL_Float_Array;
> > 		z   : PLFLT_Ptr_Array;
> > 		nx  : PLINT;
> > 		ny  : PLINT;
> > 		opt : PLINT);
> >     pragma Import(C, plmesh, "c_plmesh");
> > end PLplotThin;
> >
> > =============== plplot.adb
> > with
> >     PLplotThin,
> >     My_Common,
> >     Interfaces.C.Pointers,
> >     Interfaces.C;
> > use
> >     PLplotThin,
> >     My_Common,
> >     Interfaces.C;
> >
> > package body PLplot is
> >
> >     procedure Mesh_3D
> >        (x, y    : Long_Float_Array_1D;
> >         z       : in out Long_Float_Array_2D;
> >         Options : Integer) is
> >
> >         Index_Of_First_Column : Integer := z'First(2);
> >
> >        Pointer_Array : PLFLT_Ptr_Array(z'range(1));
> >
> >    begin
> >        for Index in z'range(1) loop
> >            Pointer_Array(Index) := z(Index, Index_Of_First_Column)'access;
>
> Use Unchecked_Access here.

I tried that before and got a segfault.

>
> >       end loop;
> >      plmesh(x, y, Pointer_Array, x'Length, y'Length, Options);
> >    end Mesh_3D;
> > end PLplot;
>
> --
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Best,
Jerry




^ permalink raw reply	[relevance 0%]

* Re: How to pass two dimensional arrays to C
  2006-08-02  8:20  6% ` Jerry
@ 2006-08-02  9:03  0%   ` Dmitry A. Kazakov
  2006-08-02 10:22  0%     ` Jerry
  2006-08-02 18:25  0%   ` Björn Persson
  1 sibling, 1 reply; 144+ results
From: Dmitry A. Kazakov @ 2006-08-02  9:03 UTC (permalink / raw)


On 2 Aug 2006 01:20:34 -0700, Jerry wrote:

> =============== my_common.ads
> package My_Common is
>     type Long_Float_Array_1D is array (Integer range <>) of aliased
> Long_Float;
>     type Long_Float_Array_2D is array (Integer range <>, integer range
> <>) of aliased Long_Float;

You cannot be sure that Integer is Interfaces.C.Int and Long_Float is 
Interfaces.C.Double.

> end My_Common;
> 
> =============== plplotthin.ads
> with
>     Interfaces.C,
>     Interfaces.C.Pointers,
>     My_Common;
> use
>     Interfaces.C,
>     Ada.Text_IO;
> 
> package PLplotThin is
>     subtype PLINT  is Integer;
>     subtype PLFLT  is Long_Float;

Same as above.

>     subtype PL_Float_Array    is My_Common.Long_Float_Array_1D;
>     subtype PL_Float_Array_2D is My_Common.Long_Float_Array_2D;
> 
>     package PLFLT_Pointers is new Interfaces.C.Pointers
>        (Index              => PLINT,
>         Element            => PLFLT,
>         Element_Array      => PL_Float_Array, -- was PLFLT_Array
>         Default_Terminator => 0.0);
>     subtype PLFLT_Ptr is PLFLT_Pointers.Pointer;
>     type PLFLT_Ptr_Array is array (PLINT range <>) of aliased
> PLFLT_Ptr;
> 
>     procedure plmesh(
> 		x   : PL_Float_Array;
> 		y   : PL_Float_Array;
> 		z   : PLFLT_Ptr_Array;
> 		nx  : PLINT;
> 		ny  : PLINT;
> 		opt : PLINT);
>     pragma Import(C, plmesh, "c_plmesh");
> end PLplotThin;
> 
> =============== plplot.adb
> with
>     PLplotThin,
>     My_Common,
>     Interfaces.C.Pointers,
>     Interfaces.C;
> use
>     PLplotThin,
>     My_Common,
>     Interfaces.C;
> 
> package body PLplot is
> 
>     procedure Mesh_3D
>        (x, y    : Long_Float_Array_1D;
>         z       : in out Long_Float_Array_2D;
>         Options : Integer) is
> 
>         Index_Of_First_Column : Integer := z'First(2);
> 
>        Pointer_Array : PLFLT_Ptr_Array(z'range(1));
>
>    begin
>        for Index in z'range(1) loop
>            Pointer_Array(Index) := z(Index, Index_Of_First_Column)'access;

Use Unchecked_Access here.

>       end loop;
>      plmesh(x, y, Pointer_Array, x'Length, y'Length, Options);
>    end Mesh_3D;
> end PLplot;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 0%]

* Re: How to pass two dimensional arrays to C
    2006-07-28 12:27  7% ` Dmitry A. Kazakov
@ 2006-08-02  8:20  6% ` Jerry
  2006-08-02  9:03  0%   ` Dmitry A. Kazakov
  2006-08-02 18:25  0%   ` Björn Persson
  2006-08-05  1:03  5% ` Jerry
  2 siblings, 2 replies; 144+ results
From: Jerry @ 2006-08-02  8:20 UTC (permalink / raw)


I have attempted to implement the approach suggested by Dmitry and
Björn. With apologies for a posting a fair bit of code, here is an
abbreviated version of what I currently have, with file names (GNAT)
indicated by =====. I hope I haven't edited out something relevant.

=============== my_common.ads
package My_Common is
    type Long_Float_Array_1D is array (Integer range <>) of aliased
Long_Float;
    type Long_Float_Array_2D is array (Integer range <>, integer range
<>) of aliased Long_Float;
end My_Common;



=============== plplotthin.ads
with
    Interfaces.C,
    Interfaces.C.Pointers,
    My_Common;
use
    Interfaces.C,
    Ada.Text_IO;

package PLplotThin is
    subtype PLINT  is Integer;
    subtype PLFLT  is Long_Float;
    subtype PL_Float_Array    is My_Common.Long_Float_Array_1D;
    subtype PL_Float_Array_2D is My_Common.Long_Float_Array_2D;

    package PLFLT_Pointers is new Interfaces.C.Pointers
       (Index              => PLINT,
        Element            => PLFLT,
        Element_Array      => PL_Float_Array, -- was PLFLT_Array
        Default_Terminator => 0.0);
    subtype PLFLT_Ptr is PLFLT_Pointers.Pointer;
    type PLFLT_Ptr_Array is array (PLINT range <>) of aliased
PLFLT_Ptr;

    procedure plmesh(
		x   : PL_Float_Array;
		y   : PL_Float_Array;
		z   : PLFLT_Ptr_Array;
		nx  : PLINT;
		ny  : PLINT;
		opt : PLINT);
    pragma Import(C, plmesh, "c_plmesh");
end PLplotThin;


=============== plplot.adb
with
    PLplotThin,
    My_Common,
    Interfaces.C.Pointers,
    Interfaces.C;
use
    PLplotThin,
    My_Common,
    Interfaces.C;

package body PLplot is

    procedure Mesh_3D
       (x, y    : Long_Float_Array_1D;
        z       : in out Long_Float_Array_2D;
        Options : Integer) is

        Index_Of_First_Column : Integer := z'First(2);

--        package PLFLT_Pointers is new Interfaces.C.Pointers
--           (Index              => PLINT,
--            Element            => PLFLT,
--            Element_Array      => PL_Float_Array, -- was PLFLT_Array
--            Default_Terminator => 0.0);
--
--        subtype PLFLT_Ptr is PLFLT_Pointers.Pointer;
--        type PLFLT_Ptr_Array is array (PLINT range <>) of aliased
PLFLT_Ptr;

        Pointer_Array : PLFLT_Ptr_Array(z'range(1));

    begin
        for Index in z'range(1) loop
            Pointer_Array(Index) := z(Index,
Index_Of_First_Column)'access;
        end loop;
        plmesh(x, y, Pointer_Array, x'Length, y'Length, Options);
    end Mesh_3D;
end PLplot;



This generates one compile-time error, "plplot.adb:990:37: non-local
pointer cannot point to local object." With a rather lucky google hit,
I was led to Cohen's book, 2nd edition, page 356, where he states the
"Acces-Type Lifetime Rule: An attribute X'Access yielding a result
belonging to an access type T is only allowed if X can remain in
existence at least as long as T."

That kinda made sense to me, so I moved the declaration of the package
PLFLT_Pointers is new Interfaces.C.Pointers along with its two
associated subtype and type declarations inside the scope of procedure
Mesh_3D, where you can see it commented-out above. With this
uncommented and the similar declarations in plplotthin.ads
commented-out, I get the compile error "plplotthin.ads:1025:56:
"PLFLT_Ptr_Array" is undefined." Duh.

So how do I fix this conundrum?

Jerry




^ permalink raw reply	[relevance 6%]

* Re: How to pass two dimensional arrays to C
  @ 2006-07-28 12:27  7% ` Dmitry A. Kazakov
  2006-08-02  8:20  6% ` Jerry
  2006-08-05  1:03  5% ` Jerry
  2 siblings, 0 replies; 144+ results
From: Dmitry A. Kazakov @ 2006-07-28 12:27 UTC (permalink / raw)


On 28 Jul 2006 04:06:59 -0700, Jerry wrote:

> In my project to write a binding for a popular plotter written in C,
> I've hit a brick wall and the problem might be associated with passing
> two-dimensionaal arrays to C.

Well, C does not have arrays (of either dimensionality), so you cannot pass
an Ada (true) array to C, as-is. You can pass a pointer to its first
element. 2D arrays in C are often emulated by using pointers to pointers.
This structure is even more distant from Ada's 2D array.

> I'm using GNAT on OS X and Xcode. I can
> pass one-dimensional arrays OK. Here are the pertinent parts from an
> example where the problem happens:
> 
>       The C
> 
> typedef double PLFLT;
> typedef int PLINT;
> 
> void c_plmesh(PLFLT *x, PLFLT *y, PLFLT **z, PLINT nx, PLINT ny, PLINT
> opt);

[...] 
> This appears during the call to plmesh. Any ideas? 

I'd suggest you to start with the Annex B.3. What you need is probably

with Interfaces.C;
with Interfaces.C.Pointers;

type PLFLT is new Interfaces.C.Double;
type PLINT is new Interfaces.C.Int;

type PLFLT_Array is array (PLINT range <>) of aliased PLFLT;
package PLFLT_Pointers is
   new Interfaces.C.Pointers
       (  Index              => PLINT,
          Element            => PLFLT,
          Element_Array      => PLFLT_Array,
          Default_Terminator => 0.0
       );
subtype PLFLT_Ptr is PLFLT_Pointers.Pointer;

type PLFLT_Ptr_Array is array (PLINT range <>) of aliased PLFLT_Ptr;
package PLFLT_Pointers_To_Pointers is
   new Interfaces.C.Pointers
       (  Index              => PLINT,
          Element            => PLFLT_Ptr,
          Element_Array      => PLFLT_Ptr_Array,
          Default_Terminator => null
       );
subtype PLFLT_Ptr_Ptr is PLFLT_Pointers_To_Pointers.Pointer;

procedure plmesh
          (  x   : PLFLT_Ptr;
             y   : PLFLT_Ptr;
             z   : PLFLT_Ptr_Ptr;
             nx  : PLINT;
             ny  : PLINT;
             opt : PLINT
          );
pragma Import(C, plmesh, "c_plmesh"); 

You might wish to write a wrapper to plmesh to be able to pass PLFLT_Array
and PLFLT_Ptr_Array down to it.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 7%]

* Re: binding to C: popen
  @ 2006-02-21 16:12  6%     ` Alex R. Mosteo
  0 siblings, 0 replies; 144+ results
From: Alex R. Mosteo @ 2006-02-21 16:12 UTC (permalink / raw)


Poul-Erik Andreasen wrote:
> jimmaureenrogers@worldnet.att.net wrote:
> 
>> Poul-Erik Andreasen wrote:
>>
>>> This ictually going as it is suppose to, but i would like set in an
>>> exception if the piping dosn't have succes. Acording to the C manual
>>> popen returns null if it fails. But how do i test on that in the 
>>> FILEs type?
>>
>>
>>
>> The popen man page describes the command as:
>> FILE *popen(const char *command, const char *mode);
>>
>> Note that popen returns a file pointer. Upon failure it returns a null
>> pointer.
>>
>> It seems that you might be able to test if the return value is null.
>>
>> Jim Rogers
>>
> 
> Yes but a C pointer is in Ada represented as system.address (...)

Not necessarily. Have a look at Interfaces.C, Interfaces.C.Pointers and 
Interfaces.C.Strings.

Also with Gnat an access type with pragma Convention (C, ...) can do the 
trick. You can easily check for null pointers that way.



^ permalink raw reply	[relevance 6%]

* Re: ++ of C in ada
  @ 2005-07-25 13:18  5% ` Marc A. Criley
  0 siblings, 0 replies; 144+ results
From: Marc A. Criley @ 2005-07-25 13:18 UTC (permalink / raw)


nicolas.b wrote:
> How can i implement the operator ++ in ada :
> 
> type T_Ptr is access all T_Item;
> How can i implement : procedure Increment (Ptr : in out T_Ptr);
> thanks
> 

See package Interfaces.C.Pointers.  Section B.3.2 in the Ada LRM 
(http://www.adapower.com/rm95/RM-B-3-2.html).

Think twice before going with this approach, though.  Is it really 
necessary, or are you just carrying through a C/C++ idiom?

-- Marc A. Criley
-- www.mckae.com
-- DTraq - XPath In Ada - XML EZ Out



^ permalink raw reply	[relevance 5%]

* Re: Returning data from Ada to C
  @ 2005-05-07 22:12  6%       ` igor.kh
  0 siblings, 0 replies; 144+ results
From: igor.kh @ 2005-05-07 22:12 UTC (permalink / raw)


Jeffrey Carter wrote:
> Igor Khavkine wrote:

> > Great! Now, what type will `Solvec' have? I presume that GNAT will
> > bark at me if I use the wrong type.
>
> In Ada, it's a pointer to Double; to C it should look like a pointer
> to double. You probably should declare your array type to be
> convention C, just to be on the safe side.

I've tried to construct a simple example where this would work.
However, I am still failing. I can't get the types to match up. Below
are the files that I'm using. The exact error from gnat is:

hello_world.adb:18:19: expected type "Interfaces.C.Pointers.Pointer"
from instance at c_integer_arrays.ads:6

== c_integer_arrays.ads ================
with Interfaces.C; use Interfaces.C;
with Interfaces.C.Pointers;

package C_Integer_Arrays is
	type C_Integer_Array is array (size_t range <>) of aliased int;
	package C_IntArrs is
		new Interfaces.C.Pointers(size_t, int,
			C_Integer_Array, 0);
end C_Integer_Arrays;
========================================

== hello_world.ads =====================
with Interfaces.C; use Interfaces.C;
with C_Integer_Arrays; use C_Integer_Arrays;

procedure Hello_World ( i : in out integer; a_ptr : out
C_IntArrs.Pointer );
pragma Export (C, Hello_World);
========================================

== hello_world.adb =====================
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

with Interfaces.C; use Interfaces.C;
with C_Integer_Arrays; use C_Integer_Arrays;

procedure Hello_World ( i : in out integer;
	a_ptr : out C_IntArrs.Pointer ) is
	a : aliased array(0..2) of int;
	pragma Convention (C, a);
begin
	Put ("Hello world!");
	Put (i);
	i := 10;
	a(0) := 3;
	a(1) := 2;
	a(2) := 1;
	a_ptr := a'Unchecked_Access;
end Hello_World;
========================================

== hello.c =============================
#include <stdio.h>

void adainit();
void adafinal();
void hello_world(int *i, int **a_ptr);

int main()
{
	int i = 1;
	int *a_ptr;

	printf ("Calling Ada...\n");

	adainit();
	hello_world(&i, &a_ptr);

	printf ("...done\n");
	printf ("Returned i = %d\n", i);
	for (i=0; i<3; i++)
		printf ("a_ptr[%d] = %d\n", i, a_ptr[i]);

	adafinal();

	return 0;
}
========================================

What am I missing to make this work?

Thanks in advance.

Igor




^ permalink raw reply	[relevance 6%]

* Returning data from Ada to C
@ 2005-05-03 23:49  5% igor.kh
    0 siblings, 1 reply; 144+ results
From: igor.kh @ 2005-05-03 23:49 UTC (permalink / raw)


I want to make use of an Ada package from some C code. I already have
something that does almost what I want, but I need to figure out how to
return some data from Ada to C. I've never worked with Ada before, so
please pardon my ignorance.

Here's the setup. I have a C file:

---- main.c ----
#include <stdio.h>

extern void adainit();
extern void adafinal();
extern void _ada_phc_direct_solver ( ..., int *rcnt, double **solvec );

int main ()
{
  int rcnt;
  double *solvec;
  int i, j, n;

  /* Do some initializations. */
  ...

  /* I want the Ada code to store a pointer in `solvec'. */
  adainit();
  _ada_phc_direct_solver(..., &rcnt, &solvec);
  adafinal();
  /* BTW, is it OK to use Ada allocated memory after `adafinal()'? */

  /* Print results. */
  printf ("Root count: %d\n", rcnt);
  printf ("Roots: Re Im\n");
  for (i=0; i<rcnt; i++)
  {
    for (j=0; j<n; j++)
      printf ("%f %f\n", solvec[rcnt*n+2*j], solvec[rcnt*n+2*j+1]);
    printf ("\n");
  }

  return 0;
}
----------------

The Ada package uses its own suite of types to interface to C. I'll try
to provide their definitions as I understand them. The Ada side of this
looks like this:

---- phc_direct_solver.adb ----
procedure phc_direct_solver (..., rcnt : out integer;
		             solvec : out C_dblarrs.Pointer ) is

-- I'm not really sure how C_dblarrs.Pointer is defined, the closest
-- definition I can find is
--
--  type C_Double_Array is
--    array ( Interfaces.C.size_t range <> ) of aliased
Interfaces.C.double;
--
--  package C_DblArrs is
--    new Interfaces.C.Pointers(Interfaces.C.size_t,
--                              Interfaces.C.double,
--                              C_Double_Array,0.0);
--
-- Perhaps I should be using another type, but I don't know which one.

  rc : integer;
  sols : C_Double_Array; -- This is probably wrong, but `sols' will be
                         -- a C_Double_Array of some size.

begin
-- Calculate `rc' and `sols'.
  ...

-- Now I want to return `rcnt' and `sols'
  rcnt := rc;                -- This is the easy part.
  solvec := ???              -- What goes here?

end phc_direct_solver;
-------------------------------

Basically, the Ada code creates an array which I want pass back to the
C
code through a pointer. Unfortunately, I'm not familiar enough with Ada
figure out how to do that. Any help or suggestions would be
appreciated.

A related question. I'm using GNAT as the compiler. I read the section
in the documentation about linking a main C program with Ada auxiliary
Ada code. But it looks like the linking can only be done with gnatlink
at the final stage, when the executable is created. Is there a way to
compile the Ada code directly into a .o or .so object file that can be
linked normally with gcc?

Thanks in advance.

Igor

P.S.: For those who are curious, I'm trying to make use of PHCpack[1]
to
solve a system of polynomial equations. I'm working from the existing
example ts_phc_solver.c.

[1] http://www2.math.uic.edu/~jan/download.html




^ permalink raw reply	[relevance 5%]

* Re: Translate from C
  @ 2005-04-11 13:39  4% ` Steve
  0 siblings, 0 replies; 144+ results
From: Steve @ 2005-04-11 13:39 UTC (permalink / raw)


First:
  It is very un-Ada like to blindly copy values fromone address to another 
in Ada.
  In Ada you tend to think of things at a higher level than C.

Second:
  There are very rare cases where you do want to copy a block of memory from 
one address to another.
  In these cases there is a function in Interfaces.C.Pointers called 
"Copy_Array" that performs exactly this function.

It would be better if you described the functionality you're looking for. 
We often see questions on this group along the lines of "This is how I do it 
in C, how do I do it the same way in Ada?".  More often than not, the better 
question is "This is what I am doing in C, how do I do the same thing in 
Ada?".  Often Ada provides a better way of doing things that results in 
fewer bugs making it past the compiler.

Steve
(The Duck)


"Jean-Baptiste CAMPESATO" <camje_lemon@a2lf.org> wrote in message 
news:pan.2005.04.09.19.30.30.254343@a2lf.org...
> Hello,
> I've this code in C : http://www.a2lf.org/util.c
> and i want to translate it in Ada;
> A friend tried :
>   procedure Copy
>     (Source      : Address;
>      Destination : Address;
>      Bytes       : Natural)
>   is
>      S : String (1 .. Bytes);
>      D : String (1 .. Bytes);
>      for S'Address use Source;
>      for D'Address use Destination;
>   begin
>      for I in S'Range loop
>         D (I) := S (I);
>      end loop;
>   end Copy;
>
> Do you think it's Ok ?
>
> Thanks. 





^ permalink raw reply	[relevance 4%]

* Re: 10 rules for benchmarking (was Re: Teaching new tricks to an old dog (C++ -->Ada))
  @ 2005-03-13 10:31  5%                                             ` Georg Bauhaus
  0 siblings, 0 replies; 144+ results
From: Georg Bauhaus @ 2005-03-13 10:31 UTC (permalink / raw)


CTips wrote:

  [a C program for measureing p[i] in Ada]

Ada program below. It isn't really much longer than the C program
as some seem to have expected.

> This is not intended to be a real program; it is meant to illustrate how 
> much slower Ada can get than C. Try and write it as specified and 
> measure the resulting performance.

Done. Performance: either a 10%--50% slowdown, or exactly the
same speed.

The  "Ada" program below has values for N and N2 so that I am at least
seing some repeatable figures, but I have tried other values as well.
(The L2 processor cache is 256k bytes in size). The C program used
for comparison has the exact same values.

As you suggested, I have not tried to write an Ada program really,
but instead to write the same program using Ada for writing C.
The result is twofold:

1) The execution speed of Ada is either much less, 0.92 vs 1.36, or
2) The execution speed is the same, 0.92 vs 0.92.

For reasons of explanation, (2) is achieved when you remove a
null pointer check that Ada requires for pointer p when doing
pointer arithmentic, that is when computing p[1]. The pointer
arithmetic function "+" from  Interfaces.C.Pointers has been
modified so that it omits the null test. But
DON'T DO THIS when writing Ada programs, you are messing
with Ada's meaning! Ada programs don't do arithmetic on null
pointers!)

    function "+" (Left : Pointer; Right : ptrdiff_t) return Pointer is
    begin
--C     if Left = null then
--C         raise Pointer_Error;
--C      end if;

       return To_Pointer (To_Addr (Left) + To_Addr (Elmt_Size * Right));
    end "+";

With this change the "Ada" program is exactly as fast as the C
program. I hear the opportunist say that you have to modify the
Ada library in order to get fast programs... Oh well, so much
for rationality in language comparisons ...


gcc -O2 -ansi -pedantic (C)
gnatmake -O2 -gnatp -gnatN (Ada)

GCC 4.0.0 20050215, 2xPIII 800MHz 256k, 1G, load low, no jobs.
$ while true ; do ./a.out ; done     # done many times


with Perm_Arrays;

procedure c is
    use Perm_Arrays;

    p, q: Int_Array(0 .. N);
    x: Ptr_Array(0 .. N2);

begin
    setup_array(x, p, q);
    for i in 1 .. 30_000 loop
       do_array(x);
    end loop;
end c;

with Interfaces.C.Pointers;

package Perm_Arrays is
    use Interfaces;

    N: constant := 3000;
    N2: constant := 6000;

    type Int_Array is array (Natural range <>) of aliased Integer;
    type Int_Ptr is access all Integer;

    package Int_Arrays is
      new C.Pointers(Natural, Integer, Int_Array, -1);

    type Ptr_Array is array (Natural range <>) of Int_Arrays.Pointer;

    procedure do_array(x: in Ptr_Array);
    procedure setup_array(x: out Ptr_Array; p, q: in out Int_Array);

end Perm_Arrays;


package body Perm_Arrays is

    use Int_Arrays;

    procedure do_array(x: in Ptr_Array) is
       p: Pointer;
    begin
       for i in x'range loop
          p := x(i);
          increment(p);
          p.all := i;
       end loop;
    end do_array;

    procedure setup_array(x: out Ptr_Array; p, q: in out Int_Array) is
    begin
       for i in p'range loop
          x(i) := p(i)'unchecked_access;
          x(i + N) := q(i)'unchecked_access;
       end loop;
    end setup_array;

end Perm_Arrays;


--  Georg



^ permalink raw reply	[relevance 5%]

* Re: Memory limits in Ada where Fortran has none
  @ 2005-03-06 23:09  4%         ` Craig Carey
  0 siblings, 0 replies; 144+ results
From: Craig Carey @ 2005-03-06 23:09 UTC (permalink / raw)




I guess that the FORTRAN was leaving too little memory for the Ada 95
 program.


On 6 Mar 2005 08:14:21 -0800, "braver" <deliverable@gmail.com> wrote:

>My working solution is probably what you mean by access function.
...
>>From now on, I allocate data arrays longer than 256*256*1024 elements
>in Fortran.  As people guessed correctly, I use GNAT -- what else can I
>do on Linux, given I can't find a downloadable/trial copy of Rational
>Apex, even though IBM took over it?  As for patches -- anyone heard of
>a 32-bit 'Size / 'Storage_Size patch to GNAT?


I guess that allocating memory on the Ada 95 side is not needed.

Maybe a thin pointer to a not allocated huge array could be used. E.g.: 

   type AA is array (Positive range <>) of ...;
   type Huge is array AA (Positive)
   Type Huge_Ptr is access Huge;
   F : Heap_Array_Ptr := new ....    --  A fat array double pointer
   X : Huge_Ptr := unchecked conversion from (F (F'First));
      --  Upper bound range checking on indexing X is absent

When importing a FORTRAN array into Ada 95, there is a choice of:
* an allocated array, or
* a pointer to a not allocated array. If the size is not known then it
   can be an array that is too large to allocate.

A pointer to the 1st element of any array including a FORTRAN array is
converted to a super large array. That zaps the upper bound index
checking.

So adding pointers can be avoided using indexing.
(If not, then GNAT source code of the gcc.gnu.org package
"Interfaces.C.Pointers" could be adapted.)

Also, there is the GNAT linker options allowing the stack size and heap
 size to be altered. They are described in the GNAT User's Guide:

gnatmake ... -largs --stack=0x30000"

The GNAT Users guide says:

$ gnatlink hello -Xlinker --stack=0x10000,0x1000

"This set the stack reserve size to 0x10000 bytes and the stack commit
 size to 0x1000 bytes."

$ gnatlink hello -Xlinker --heap=0x10000,0x1000
"This set the heap reserve size to 0x10000 bytes and the heap commit size
 to 0x1000 bytes."


On 6 Mar 2005 14:13:13 -0800, Gerald wrote:
...
>You should dynamically allocate the big array:
...
Hmm


--  Craig Carey <research@ijs.co.nz>    Avondale, Auckland, New Zealand
--  Fairness checklist: http://www.ombudsman.on.ca/pdf/fairness_stds.pdf
--  Ada 95 mailing lists: http://www.ijs.co.nz/ada_95.htm





^ permalink raw reply	[relevance 4%]

* Re: Ada equivalent to &#1057;++ header sentence.
  2004-08-20 12:37  4% ` Stephen Leake
@ 2004-08-24  3:32  5%   ` Randy Brukardt
  0 siblings, 0 replies; 144+ results
From: Randy Brukardt @ 2004-08-24  3:32 UTC (permalink / raw)


"Stephen Leake" <stephen_leake@acm.org> wrote in message
news:mailman.5.1093005464.28011.comp.lang.ada@ada-france.org...
> rhezusfactor@yahoo.com (Johnswort) writes:
...
> > Presumingly, LPSTR may come from Win32.
>
> Yes, it stands for "Long Pointer to String". You might be tempted to
> define it in Ada as:
>
> type LPSTR is access String; --  WRONG!
>
> But since an Ada string is an Ada array, and a C string is just a
> pointer to Char, this is wrong. You can use Interfaces.C.Pointers, but
> that gets very cumbersome. Use System.Address, and make sure you
> append ASCII.Nul to the end of any strings passed to C.

I was with you until this point, but I don't agree with the advice to use
System.Address. Using it in Ada 95 (other than with an address clause)
represents a design mistake in my view.

Claw defines LPStr as
    type LPStr is access all Interfaces.C.Char;

and uses the Interfaces.C To_C and To_Ada functions to do the needed
conversions. Note that Interfaces.C.Char_Array has aliased components, so
that
    Name(Name'First)'Access
passes the first character of a Char_Array, (and thus the whole array in C
terms).

This has the advantage of being more strongly typed - it's still possible to
pass a char array that's not null terminated, but you can't accidentially
pass an array of integers or (more commonly) some record type.
Rule of thumb: Never, ever write weakly typed code when it's reasonable to
write strongly typed code.

An alternative is to use Interfaces.C.Strings (there's no reason to mess
with Interfaces.C.Pointers for this), but it tends to make you do some
storage management that's usually unnecessary. (We also didn't have it
working in Janus/Ada when we started Claw, which is probably really why we
avoided it.)

                    Randy.






^ permalink raw reply	[relevance 5%]

* Re: Ada equivalent to &#1057;++ header sentence.
  @ 2004-08-20 12:37  4% ` Stephen Leake
  2004-08-24  3:32  5%   ` Randy Brukardt
  0 siblings, 1 reply; 144+ results
From: Stephen Leake @ 2004-08-20 12:37 UTC (permalink / raw)
  To: comp.lang.ada

rhezusfactor@yahoo.com (Johnswort) writes:

> I try to make a binding on an API, which has a header in C++ syntax.
> As a complete moron in both C/C++, I want to grab the last straw
> before giving up. So I ask for a hint: what would be the Ada
> equivalent to the following:
> 
> typedef BOOL                    (_stdcall T_hcConnect)(LPSTR lszCmd);

This declares T_hcConnect to be a type designating a function that
takes an LPSTR parameter and returns a BOOL result. The normal use in
C for such a type is to designate a pointer to a function. So the
equivalent in Ada is a function access type:

type T_hcConnect is access function (lszCmd : in LPSTR) return BOOL;

> Presumingly, LPSTR may come from Win32. 

Yes, it stands for "Long Pointer to String". You might be tempted to
define it in Ada as:

type LPSTR is access String; --  WRONG!

But since an Ada string is an Ada array, and a C string is just a
pointer to Char, this is wrong. You can use Interfaces.C.Pointers, but
that gets very cumbersome. Use System.Address, and make sure you
append ASCII.Nul to the end of any strings passed to C.

> Just in case, VB header translates it into
> 
> Declare Function hbConnect Lib "hapi.dll" Alias "hcConnect" (ByVal
> command As String) As Long

That's similar. But VB puts wrappers around such functions for you, so
it's not completely identical. For instance, it's not a type.

Since you appear to be importing a DLL, there are better ways than
declaring function access types. Read the GNAT user guide section on
importing DLLs. Or, as someone else pointed out, try using GNATCOM.

-- 
-- Stephe




^ permalink raw reply	[relevance 4%]

* Re: Ada access vs C/C++ pointers and references
  @ 2004-08-19  0:21  6% ` Nick Roberts
  0 siblings, 0 replies; 144+ results
From: Nick Roberts @ 2004-08-19  0:21 UTC (permalink / raw)


On 18 Aug 2004 15:27:47 -0700, Keith H Duggar <duggar@mit.edu> wrote:

> [re array indexing]
> As you can see, method two saves one instruction by storing
> and manipulating a memory address directly.

In a loop, there is well known optimisation known (for reasons which
mystify me) as 'strength reduction', which allows a loop such as:

    for (i=0;i<n;i++) { ... a[i] ... };

to be transformed into the equivalent of:

    for (p=&a[0];p<&a[n];p++) { ... *p ... };

before emitting machine code. So an Ada loop such as:

    for i in 1..N loop
       ... A(i) ...
    end loop;

can be expected to be compiled into machine code which is as
efficient as the code that could be produced by using direct address
manipulation.

> First, is it correct to say that Ada access types are more
> similar to C++ references (T&) than they are to C/C++
> pointers (T*) ?

No. Ada access types are very similar to C and C++ pointers, and are
typically implemented and used in (almost) exactly the same way.

The rough Ada equivalent of C++ references are 'aliased objects'.

> Second, does Ada provide any facilities for direct and raw
> memory access by memory address and pointer arithmetic?

Yes it does. There are standard packages System.Storage_Elements and
System.Address_To_Access_Conversions, which provide facilities for
converting between access types and addresses, and performing integer
arithmetic on addresses, as well as Interfaces.C and
Interfaces.C.Pointers which enable Ada programs to access C strings,
arrays, and pointers.

> Third, if Ada does not provide arithmetic pointers do you
> know if this has played any part in acceptance of Ada for
> systems programming or efficiency critical applications?

I don't know (sorry).

> Fourth, have you experienced or can you think of any cases
> where pointer arithmetic has helped to solve a problem that
> would have been more difficult with Ada access types alone?

Not that I can recall.

-- 
Nick Roberts



^ permalink raw reply	[relevance 6%]

* Re: Question on interface Ada to C
  @ 2004-05-26  7:34  5% ` Martin Krischik
  0 siblings, 0 replies; 144+ results
From: Martin Krischik @ 2004-05-26  7:34 UTC (permalink / raw)


James Alan Farrell wrote:

> Hello all,

> I've inherited a project that is half written in C and Ada.

Nothing wrong with that. You should carfully read Annex B. Currently I do a
lot of Ada / C mixed programming as well. It works quite well.

> My boss at first thought this was good code but when he took a second
> look he wasn't so sure.  So he's asked me to investigate.  What
> exactly happens with the memory used by list in this situation?

The code is indeed not very good.

> We're using GNAT, but I don't think that's an issue -- I would think
> this code would behave (or misbehave) the same no matter what
> compiler.

That depends if you use GNAT with gcc's own C or GNAT with some other C. 

> Thanks,
> James Alan Farrell
> GrammaTech.
> 
>  type stuff is integer; -- just for example
> 
>  type List_Type is array(Integer range <>) of stuff;
>  
>  package MyPointers is
>               new System.Address_To_Access_Conversions(List_Type);
>  subtype List_Pointer is MyPointers.Object_Pointer;
> 
>  procedure MyProc
>      (Items     : in out List_Pointer;
>       Nitems    : in out Integer) is
> 
>       List : List_Type := function_that_returns_a_list;
> 
>    begin
>       Nitems := List'Length;
>       Items  := MyPointers.To_Pointer(List'Address);
>    end;

List will be short lived after MyProc ends. Also list is indefinite - C has
no conzept of indefinite.

You should return a record like this (Example for Character):

----------------------------------------------------------------------------

   --
   --  C/Ada String Type
   --
   type C_Array
   is array
      (Natural range <>)
   of aliased
      Character;

----------------------------------------------------------------------------

   package C_Pointers
   is new
      Interfaces.C.Pointers (
         Index              => Natural,
         Element            => Character,
         Element_Array      => C_Array,
         Default_Terminator => Character'First);

----------------------------------------------------------------------------

   type C_String
   is record
      Data : C_Pointers.Pointer;
      Size : Interfaces.C.size_t;
   end record;

With GNAT you can use function as well. Returning a record from Ada to C
work OK.

C_String.Data should be allocated and freed with malloc. See:

http://cvs.sourceforge.net/viewcvs.py/adacl/CUnicode/Include/c-generic_strings.adb?rev=1.5&view=auto

If you use GNAT only then you can import malloc directly.

With Regards

Martin

-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com




^ permalink raw reply	[relevance 5%]

* Re: C bindings, Interfaces.C.Pointers etc.
  2004-05-13 15:56  5%   ` Dr. Adrian Wrigley
  2004-05-13 17:37 13%     ` Martin Krischik
@ 2004-05-13 22:42  8%     ` Jeffrey Carter
  1 sibling, 0 replies; 144+ results
From: Jeffrey Carter @ 2004-05-13 22:42 UTC (permalink / raw)


Dr. Adrian Wrigley wrote:
> Thanks Martin for this suggestion.
> 
> I have given (an approximation of) my code below.
> 
> It doesn't use the I.C.Pointers package, and allows
> Ada programs to access elements of the arrays using
> standard array notation.  The main problem is that
> the bound Ada uses are over-sized, and simple use
> of 'range and 'last will fall off the ends.

Once you have an acceptable "oversized" Ada array, you can slice it to 
obtain a usable Ada array of the correct size.

-- 
Jeff Carter
"Sir Robin the-not-quite-so-brave-as-Sir-Lancelot,
who had nearly fought the Dragon of Angnor,
who nearly stood up to the vicious Chicken of Bristol,
and who had personally wet himself at the
Battle of Badon Hill."
Monty Python & the Holy Grail
68




^ permalink raw reply	[relevance 8%]

* Re: C bindings, Interfaces.C.Pointers etc.
  2004-05-13 15:56  5%   ` Dr. Adrian Wrigley
@ 2004-05-13 17:37 13%     ` Martin Krischik
  2004-05-13 22:42  8%     ` Jeffrey Carter
  1 sibling, 0 replies; 144+ results
From: Martin Krischik @ 2004-05-13 17:37 UTC (permalink / raw)


Dr. Adrian Wrigley wrote:

> Thanks Martin for this suggestion.
> 
> I have given (aninvolvedimation of) my code below.
> 
> It doesn't use the I.C.Pointers package, and allows
> Ada programs to access elements of the arrays using
> standard array notation.  The main problem is that
> the bound Ada uses are over-sized, and simple use
> of 'range and 'last will fall off the ends.

There is one more way but only usable when you C and Ada compiler use the
same memory layout for variables. The example works for Strings:

   type C_Array is array (Natural range <>) of aliased Character;

   for C_Array'Component_Size use Interfaces.C.char'Size;

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

   package C_Pointers
   is new
      Interfaces.C.Pointers (
         Index              => Natural,
         Element            => Character,
         Element_Array      => C_Array,
         Default_Terminator => Character'First);

   type C_String
   is record
      --  Address of some C Array
      Data : C_Pointers.Pointer;
      --  Size of the Array.
      Size : Interfaces.C.size_t;
   end record;

Ada_String  : String (1 .. Natural (Some_C_String.Size));

for Ada_String 'Address use Some_C_String.Data.all'Address;

The trick is in the last line. This is of corse an Unchecked_Convertion
without actually moving the Data. Use at your own risk. 

You can probably reduce the code involved by using an normal access to
Character for C_String.Data.

> Overall this solution meets my needs very well, and
> if I accidentally use the invalid array (upper) bound,
> the program crashes very rapidly (like it would have
> done in C with a similar bug!).

With the trick above Ada will check the array bounds - when Size containts
the right value.
 
> I'm a little surprised that I.C.Pointers doesn't seem
> to provide a convenient and efficient solution to this
> problem - using C pointers directly in array access.

I.C.Pointers is supposed to all the checked convertions needed and will work
when C and Ada use different memory layout - at least that's the theorie.
 
With Regards

Martin.

-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com




^ permalink raw reply	[relevance 13%]

* Re: C bindings, Interfaces.C.Pointers etc.
  2004-05-12  6:30  7% ` Martin Krischik
@ 2004-05-13 15:56  5%   ` Dr. Adrian Wrigley
  2004-05-13 17:37 13%     ` Martin Krischik
  2004-05-13 22:42  8%     ` Jeffrey Carter
  0 siblings, 2 replies; 144+ results
From: Dr. Adrian Wrigley @ 2004-05-13 15:56 UTC (permalink / raw)


Thanks Martin for this suggestion.

I have given (an approximation of) my code below.

It doesn't use the I.C.Pointers package, and allows
Ada programs to access elements of the arrays using
standard array notation.  The main problem is that
the bound Ada uses are over-sized, and simple use
of 'range and 'last will fall off the ends.

I have used a generic package to create the appropriate
types needed, and wrap the "malloc" and "free".
This way, the C library can intermix allocations and
deallocations with those of the Ada code.

I put in the "aliased" - something I often forget
until the compiler complains at me!

Overall this solution meets my needs very well, and
if I accidentally use the invalid array (upper) bound,
the program crashes very rapidly (like it would have
done in C with a similar bug!).

I'm a little surprised that I.C.Pointers doesn't seem
to provide a convenient and efficient solution to this
problem - using C pointers directly in array access.

The next problem I am thinking about with this project
is how to abort a call into the C/C++ library safely.
Sometimes the library takes *much* too long to compute
a result. (If the parameters are unsuitable, it can
take hours vs seconds with good parameters).
If the thread executing the library call is aborted,
memory will hemmorage from the application.  This problem
will probably need a hacked version of the (Open Source)
library.  I'm not sure how to communicate with the
call as it executes telling it to clean up and exit
immediately.  Shared memory flags? Signals?

Thanks for the input on these problems!
--
Adrian


generic

   type Element_T is private;
   IndexBase : Integer := 0;

package CArrayUtils is

   type ElementArray_T is array (0 .. Interfaces.C.Size_T'Last) of aliased Element_T;
   pragma Convention (C, ElementArray_T);
   type ElementArray_A is access ElementArray_T;
   pragma Convention (C, ElementArray_A);

   function CAlloc (N : Integer) return ElementArray_A;
   procedure CFree (X : in out ElementArray_A);

end CArrayUtils;

package body CArrayUtils is

   function CAlloc (N : Integer) return ElementArray_A is
      function Malloc (A : Interfaces.C.Size_T) return ElementArray_A;
      pragma Import (C, Malloc, "malloc");
   begin
-- Is the size in bytes calculated correctly???  Probably not!
      return Malloc (Interfaces.C.Size_T (N * Element_T'Size / 8 + 1));
   end CAlloc;

   procedure CFree (X : in out ElementArray_A) is
      procedure Free (X : ElementArray_A);
      pragma Import (C, Free, "free");
   begin
      Free (X);
      X := null;
   end CFree;

end CArrayUtils;

with Interfaces.C;

package Blob is

  type Node_T is record
      Index : Interfaces.C.Int;
      Value : Interfaces.C.Double;
   end record;
   pragma Convention (C, Node_T);

   package NodeArray_P is new CArrayUtils (Element_T => Node_T);
   subtype NodeArray_A is NodeArray_P.ElementArray_A;

   package NodeArrayArray_P is new CArrayUtils (Element_T => NodeArray_A);
   subtype NodeArrayArray_A is NodeArrayArray_P.ElementArray_A;

   package DoubleArray_P is new CArrayUtils (Element_T => Interfaces.C.Double);
   subtype DoubleArray_A is DoubleArray_P.ElementArray_A;


   type SVMProblem_T is record
      L  : Interfaces.C.Int;
      Y  : DoubleArray_A;       -- Pointer to array of double
      X  : NodeArrayArray_A; -- (pointer to array of (pointer to array of SVMNode))
   end record;
   pragma Convention (C, Problem_T);

end Blob;




^ permalink raw reply	[relevance 5%]

* Re: C bindings, Interfaces.C.Pointers etc.
  2004-05-11 18:48  7% ` Jeffrey Carter
  2004-05-12  4:50  7%   ` Simon Wright
@ 2004-05-13 15:26  8%   ` Dr. Adrian Wrigley
  1 sibling, 0 replies; 144+ results
From: Dr. Adrian Wrigley @ 2004-05-13 15:26 UTC (permalink / raw)


On Tue, 11 May 2004 18:48:57 +0000, Jeffrey Carter wrote:

>     -- struct node { int index; double value; };
>     type Node_Info is record
>        Index : Interfaces.C.Int;
>        Value : Interfaces.C.Double;
>     end record;
>     pragma Convention (C, Node_Info);
> 
>     -- struct problem { node **x; };
>     type Node_Ptr     is access all Node_Info;
>     pragma Convention (C, Node_Ptr);
>     type Node_Ptr_Ptr is access all Node_Ptr;
>     pragma Convention (C, Node_Ptr_Ptr);
>     type Problem_Info is record
>        X : Node_Ptr_Ptr;
>     end record;
>     pragma Convention (C, Problem_Info);
> 
> This compiles fine. This is an exact duplicate of the C declarations. To 
> deal with this using a higher level Ada abstraction, you'd wrap 
> something around this to provide that abstraction.

I hadn't thought of doing this - it doesn't seem to provide easy answers
for allocation and indexing though.  In this application, I am building
data structures for use by a C/C++ library.  The wrapper you're
suggesting (I guess) is for accessing elements of the arrays,
and allocating/freeing them.  I'd have to check that the additional
code didn't impose excessive overheads.

The solution I have adopted in the end is based on my idea (4),
mentioned by tmoran and Martin Chrischik (see other messages).

Thanks!
-- 
Adrian




^ permalink raw reply	[relevance 8%]

* Re: C bindings, Interfaces.C.Pointers etc.
  2004-05-11 13:14 12% C bindings, Interfaces.C.Pointers etc Dr. Adrian Wrigley
  2004-05-11 18:17  8% ` tmoran
  2004-05-11 18:48  7% ` Jeffrey Carter
@ 2004-05-12  6:30  7% ` Martin Krischik
  2004-05-13 15:56  5%   ` Dr. Adrian Wrigley
  2 siblings, 1 reply; 144+ results
From: Martin Krischik @ 2004-05-12  6:30 UTC (permalink / raw)


Dr. Adrian Wrigley wrote:

> Hi folks!
> 
> I have a problem creating a binding to a C library.
> 
> The library makes extensive use of arrays of arrays of structs.
> Both levels of arrays are of variable length.
> 
>  struct node { int index; double value; };
>  struct problem { node **x; };
> 
> When I attempt to define Ada types for this type of thing,
> I find I can't use access types to the arrays with the
> necessary C convention.
> "warning: this access type does not correspond to C pointer"
> is the compiler error.
> 
> I have tried using Interfaces.C.Pointers, but I have run
> into (soluble?) problems.
> 
> 1)  How to I allocate an array (in Ada) and assign it to a
>    C pointer? (in a single expression?)

Ada_Array : <some array>

C_Pointer  :  constant C_Pointers.Pointer := Ada_Array (0)'Unchecked_Access;

Depending on how Ada_Array is defined it might work without Unchecked_.
 
> 2)  How do I free the allocaed array from the C pointer?
>    Do I need to keep track of the return values from "new"
>    separately from the pointers?

Since the Pointer are for use with C you might consider:

   function malloc (Size : size_t) return System.Address;
   pragma Import (C, malloc, "malloc");
   procedure free (Ptr : System.Address);
   pragma Import (C, free, "free");

You can either combine it with package System.Address_To_Access_Conversions
or a special Storrage_Pool.
 
> 3)  How do I access the n'th element of the Array, given the
>    C pointer.

Depending on actual use You can either convert the C array to an Ada array
or use:

Access_Pointer := Base_Pointer + n;

... Base_Pointer.all ...

> 4)  Is there some convenient shortcut to avoid using I.C.P?
>    perhaps by declaring an Ada constrained array much larger than
>    intended, and using a subset.
>    Using I.C.P seems massively verbose (10x) for this application.

From you example down I suggest "aliased" Elements

type NodeArray_T is array (Interfaces.C.Size_T range <>) of  aliased Node_T;
type NodeArrayArray_T is array (Interfaces.C.Size_T range <>) of aliased 
NodeArray_A;

then you can use I.C.P.Value and I.C.P.Copy_Array as alternative to pure
Pointer use. Giving you more flexibility.
 
> As I understand it, if the array is unconstrained, an access type
> to the array contains the dope information, and can't be used
> as a C pointer.
> 
> I have given an example of my problem code below (without I.C.P).

Well, it does look Ok to me. Apart from the missing "aliased". All elements
in an C array need an address while in Ada they don't. (Look for pragma
Pack and the attributes 'Size and 'Component_Size for details).

With Regards

Martin
-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com




^ permalink raw reply	[relevance 7%]

* Re: C bindings, Interfaces.C.Pointers etc.
  2004-05-11 18:48  7% ` Jeffrey Carter
@ 2004-05-12  4:50  7%   ` Simon Wright
  2004-05-13 15:26  8%   ` Dr. Adrian Wrigley
  1 sibling, 0 replies; 144+ results
From: Simon Wright @ 2004-05-12  4:50 UTC (permalink / raw)


Jeffrey Carter <spam@spam.com> writes:

> Dr. Adrian Wrigley wrote:
> 
> > Hi folks!
> > I have a problem creating a binding to a C library.
> > The library makes extensive use of arrays of arrays of structs.
> > Both levels of arrays are of variable length.
> >  struct node { int index; double value; };
> >  struct problem { node **x; };
> > When I attempt to define Ada types for this type of thing,
> > I find I can't use access types to the arrays with the
> > necessary C convention.
> > "warning: this access type does not correspond to C pointer"
> > is the compiler error.
> 
>     -- struct node { int index; double value; };
>     type Node_Info is record
>        Index : Interfaces.C.Int;
>        Value : Interfaces.C.Double;
>     end record;
>     pragma Convention (C, Node_Info);
> 
>     -- struct problem { node **x; };
>     type Node_Ptr     is access all Node_Info;
>     pragma Convention (C, Node_Ptr);
>     type Node_Ptr_Ptr is access all Node_Ptr;
>     pragma Convention (C, Node_Ptr_Ptr);
>     type Problem_Info is record
>        X : Node_Ptr_Ptr;
>     end record;
>     pragma Convention (C, Problem_Info);
> 
> This compiles fine. This is an exact duplicate of the C
> declarations.

But not, I think, of the implications. Where is the equivalent of 

  problem p;
  node *np = *p.x;
  np++;               // <<<<

I've used constrained subtypes in the past:

  type Node_Array is array (Integer range <>) of Node_Info;
  
then in a subprogram taking a Node_Array parameter Nodes,

  subtype Specific_Node_Array is Node_Array (Nodes'First .. Nodes'Last);
  type Node_Array_Access is access Specific_Node_Array;
  pragma Convention (C, Node_Array_Access);

then declare a local binding to the C operation.

Same again for Node_Ptr_Array, though the Ada side of this is going to
be rather difficult since the Node_Ptrs in this are really
Node_Array_Accesses and the Node_Arrays are not all of the same
length.

Perhaps the simplest way would be to use System.Address:

   (Arr (Arr'First))'Address

>               To deal with this using a higher level Ada
> abstraction, you'd wrap something around this to provide that
> abstraction.



-- 
Simon Wright                               100% Ada, no bugs.



^ permalink raw reply	[relevance 7%]

* Re: C bindings, Interfaces.C.Pointers etc.
  2004-05-11 13:14 12% C bindings, Interfaces.C.Pointers etc Dr. Adrian Wrigley
  2004-05-11 18:17  8% ` tmoran
@ 2004-05-11 18:48  7% ` Jeffrey Carter
  2004-05-12  4:50  7%   ` Simon Wright
  2004-05-13 15:26  8%   ` Dr. Adrian Wrigley
  2004-05-12  6:30  7% ` Martin Krischik
  2 siblings, 2 replies; 144+ results
From: Jeffrey Carter @ 2004-05-11 18:48 UTC (permalink / raw)


Dr. Adrian Wrigley wrote:

> Hi folks!
> 
> I have a problem creating a binding to a C library.
> 
> The library makes extensive use of arrays of arrays of structs.
> Both levels of arrays are of variable length.
> 
>  struct node { int index; double value; };
>  struct problem { node **x; };
> 
> When I attempt to define Ada types for this type of thing,
> I find I can't use access types to the arrays with the
> necessary C convention.
> "warning: this access type does not correspond to C pointer"
> is the compiler error.

    -- struct node { int index; double value; };
    type Node_Info is record
       Index : Interfaces.C.Int;
       Value : Interfaces.C.Double;
    end record;
    pragma Convention (C, Node_Info);

    -- struct problem { node **x; };
    type Node_Ptr     is access all Node_Info;
    pragma Convention (C, Node_Ptr);
    type Node_Ptr_Ptr is access all Node_Ptr;
    pragma Convention (C, Node_Ptr_Ptr);
    type Problem_Info is record
       X : Node_Ptr_Ptr;
    end record;
    pragma Convention (C, Problem_Info);

This compiles fine. This is an exact duplicate of the C declarations. To 
deal with this using a higher level Ada abstraction, you'd wrap 
something around this to provide that abstraction.

-- 
Jeff Carter
"Blessed is just about anyone with a vested interest in the status quo."
Monty Python's Life of Brian
73




^ permalink raw reply	[relevance 7%]

* Re: C bindings, Interfaces.C.Pointers etc.
  2004-05-11 13:14 12% C bindings, Interfaces.C.Pointers etc Dr. Adrian Wrigley
@ 2004-05-11 18:17  8% ` tmoran
  2004-05-11 18:48  7% ` Jeffrey Carter
  2004-05-12  6:30  7% ` Martin Krischik
  2 siblings, 0 replies; 144+ results
From: tmoran @ 2004-05-11 18:17 UTC (permalink / raw)


>4)  Is there some convenient shortcut to avoid using I.C.P?
>    perhaps by declaring an Ada constrained array much larger than
>    intended, and using a subset.
  That's what I'd do.  You clearly can't expect Ada to bounds check an
array that has no bounds, ie, a C array.  If C is doing all the allocating
there's no memory penalty.  If Ada is doing the allocating, you might want
to tell Ada you have a (fixed size) one dimensional array of pointers to
elements, rather than to arrays, and let C assume a pointer to a first
element is a pointer to an array.



^ permalink raw reply	[relevance 8%]

* C bindings, Interfaces.C.Pointers etc.
@ 2004-05-11 13:14 12% Dr. Adrian Wrigley
  2004-05-11 18:17  8% ` tmoran
                   ` (2 more replies)
  0 siblings, 3 replies; 144+ results
From: Dr. Adrian Wrigley @ 2004-05-11 13:14 UTC (permalink / raw)


Hi folks!

I have a problem creating a binding to a C library.

The library makes extensive use of arrays of arrays of structs.
Both levels of arrays are of variable length.

 struct node { int index; double value; };
 struct problem { node **x; };

When I attempt to define Ada types for this type of thing,
I find I can't use access types to the arrays with the
necessary C convention.
"warning: this access type does not correspond to C pointer"
is the compiler error.

I have tried using Interfaces.C.Pointers, but I have run
into (soluble?) problems.

1)  How to I allocate an array (in Ada) and assign it to a
   C pointer? (in a single expression?)

2)  How do I free the allocaed array from the C pointer?
   Do I need to keep track of the return values from "new"
   separately from the pointers?

3)  How do I access the n'th element of the Array, given the
   C pointer.

4)  Is there some convenient shortcut to avoid using I.C.P?
   perhaps by declaring an Ada constrained array much larger than
   intended, and using a subset.
   Using I.C.P seems massively verbose (10x) for this application.

As I understand it, if the array is unconstrained, an access type
to the array contains the dope information, and can't be used
as a C pointer.

I have given an example of my problem code below (without I.C.P).

Any ideas?
--
Adrian Wrigley, Cambridge, England


procedure Problem is

-- C code is:
--
-- struct node
-- {
--      int index;
--      double value;
-- };

-- struct problem
-- {
--      node **x;
-- };

-- x is a pointer to an array of pointers to arrays of nodes (both variable size)

   type Node_T is record
      Index : Interfaces.C.Int;
      Value : Interfaces.C.Double;
   end record;
   pragma Convention (C, Node_T);

   type NodeArray_T is array (Interfaces.C.Size_T range <>) of Node_T;
   pragma Convention (C, NodeArray_T);
   type NodeArray_A is access all NodeArray_T;
   pragma Convention (C, NodeArray_A);

   type NodeArrayArray_T is array (Interfaces.C.Size_T range <>) of NodeArray_A;
   pragma Convention (C, NodeArrayArray_T);
   type NodeArrayArray_A is access all NodeArrayArray_T;
   pragma Convention (C, NodeArrayArray_A);

   type Problem_T is record
      X : NodeArrayArray_A;
   end record;
   pragma Convention (C, Problem_T);

   MyProblem : Problem_T;
   MyNode : Node_T;

begin

   MyProblem := (X => new NodeArrayArray_T (1 .. 100));

   for I in MyProblem.X'range loop
      MyProblem.X (I) := new NodeArray_T (1 .. I);
   end loop;

   MyNode := MyProblem.X (10)(5);

end Problem;




^ permalink raw reply	[relevance 12%]

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-08 22:43  3%       ` Robert I. Eachus
@ 2003-10-09  9:31  0%         ` Duncan Sands
  0 siblings, 0 replies; 144+ results
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	[relevance 0%]

* Re: C array to Ada pointer to unconstrained array without copying memory
  @ 2003-10-08 22:43  3%       ` Robert I. Eachus
  2003-10-09  9:31  0%         ` Duncan Sands
  0 siblings, 1 reply; 144+ results
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	[relevance 3%]

* Re: C array to Ada pointer to unconstrained array without copying memory
       [not found]       ` <3F83540E.5000302@myob.com>
@ 2003-10-08  9:18  0%     ` Duncan Sands
  0 siblings, 0 replies; 144+ results
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	[relevance 0%]

* Re: C array to Ada pointer to unconstrained array without copying memory
  @ 2003-10-08  0:02  5%   ` sk
       [not found]       ` <3F83540E.5000302@myob.com>
  1 sibling, 0 replies; 144+ results
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	[relevance 5%]

* Re: generic imports?  void* -> generics?
  @ 2003-09-19 21:18  5% ` Nick Roberts
  0 siblings, 0 replies; 144+ results
From: Nick Roberts @ 2003-09-19 21:18 UTC (permalink / raw)


"chris" <spamoff.danx@ntlworld.com> wrote in message
news:FBIab.3309$DM5.35123@newsfep4-glfd.server.ntli.net...

> Should the following C code be mapped to a generic?
>
> void *lua_touserdata (Lua_State* L, int pos)

Not directly. I would suggest that you take the following approach.

   package Stream_C_Pointers is new Interfaces.C.Pointers(
      Index => Ada.Streams.Stream_Element_Offset,
      Element => Ada.Streams.Stream_Element,
      Element_Array => Ada.Streams.Stream_Element_Array );

   subtype Stream_C_Pointer is Stream_C_Pointers.Pointer;
   use Stream_C_Pointers;

   function LUA_To_User_Data (State: access LUA_State;
                                  Pos: Interfaces.C.int) returns
Stream_C_Pointer;

   pragma Import(C,LUA_To_User_Data,"lua_touserdata");

The general idea is that Ada code is able to read a variable from the memory
area returned by this C function, interpreted as a stream array so that the
variable's stream-oriented Read procedure or Input function can be used
directly. There could well be difficulties associated with writing data
using C code and then reading it using (stream-oriented) Ada code.

You may well wish to wrap all this up in a package or a generic package, at
a higher level of organisation.

Hope this helps. I'd be happy to give more detail if you wish.

--
Nick Roberts
Jabber: debater@charente.de [ICQ: 159718630]





^ permalink raw reply	[relevance 5%]

* Interfaces.C.Pointers
@ 2003-06-22  3:28 14% tmoran
  0 siblings, 0 replies; 144+ results
From: tmoran @ 2003-06-22  3:28 UTC (permalink / raw)


I seems to me that Interfaces.C.Pointers really isn't just about C
pointers (though that may be its main use), but the Value functions
let you convert a pointer to an element to a pointer to an array
of variable size.
  type general_array_type is array(integer range <>) of integer;
  procedure p(pi : access integer; length : natural) is

  type static is array(1 .. 3) of integer;
  x : static;
  p(x(x'first),3);
Inside procedure p, by using Interfaces.C.Pointers, you can
  my_copy : general_array_type := value(pi, ptrdiff_t(length));
Am I misunderstanding?



^ permalink raw reply	[relevance 14%]

* Re: Interfacing Ada with C
  2003-04-16  2:56  7% ` Steve
@ 2003-04-16  4:25  6%   ` Steve
  0 siblings, 0 replies; 144+ results
From: Steve @ 2003-04-16  4:25 UTC (permalink / raw)


"Steve" <nospam_steved94@attbi.com> wrote in message
news:pD3na.499811$sf5.816502@rwcrnsc52.ops.asp.att.net...
> A different way of doing this:
>
> In Ada you should be able to use Interfaces.C.Pointers and then declare
your
> procedure as follows:
>
>   package Interface_Wide_String is
>     new Interfaces.C.Pointers( Interfaces.C.size_T,
>                                Interfaces.C.WChar_T,
>                                Interfaces.C.WChar_Array,
>                                Interfaces.C.Wide_Nul );
[snip]
>
> I haven't tested this, but I think it will work (it compiles anyway).
>
> Steve
> (The Duck)
>
I created a small set of sources and tested my example (it does work).
Here's the source
for my test case:

------ File: clatest.c ------
#include <stdlib.h>

extern void One( wchar_t *text );
extern void adainit();
extern void adafinal();

int main(int argc, char* argv[])
{
    adainit();
    One( L"Hello from Ada" );
    adafinal();
    return 0;
}

------ File: One_Package.ads ------
with Interfaces.C;
with Interfaces.C.Pointers;

package One_Package is

  package Interface_Wide_String is
    new Interfaces.C.Pointers( Interfaces.C.size_T,
                               Interfaces.C.WChar_T,
                               Interfaces.C.WChar_Array,
                               Interfaces.C.Wide_Nul );

  procedure One( Name : in Interface_Wide_String.Pointer );
  pragma Export( C, One, "One" );

end One_Package;

------ File: One_Package.adb ------
with Ada.Wide_Text_Io;

package body One_Package is

  procedure One( Name : in Interface_Wide_String.Pointer ) is
  begin
    Ada.Wide_Text_Io.Put_Line( Interfaces.C.To_Ada(
Interface_Wide_String.Value( Name ) ) );
  end One;

end One_Package;

Steve
(The Duck)





^ permalink raw reply	[relevance 6%]

* Re: Interfacing Ada with C
  @ 2003-04-16  2:56  7% ` Steve
  2003-04-16  4:25  6%   ` Steve
  0 siblings, 1 reply; 144+ results
From: Steve @ 2003-04-16  2:56 UTC (permalink / raw)


A different way of doing this:

In Ada you should be able to use Interfaces.C.Pointers and then declare your
procedure as follows:

  package Interface_Wide_String is
    new Interfaces.C.Pointers( Interfaces.C.size_T,
                               Interfaces.C.WChar_T,
                               Interfaces.C.WChar_Array,
                               Interfaces.C.Wide_Nul );

  procedure One( Name : in Interface_Wide_String.Pointer );
  pragma Export( C, One );


Within procedure "One" you can use:

    myName : Wide_String := Interfaces.C.To_Ada(
Interface_Wide_String.Value( Name ) );

If you need to look at the string as a wide string.

I haven't tested this, but I think it will work (it compiles anyway).

Steve
(The Duck)


"Paul Anderson" <notme@nowhere.com> wrote in message
news:3e9b28f8$1_4@newsfeed...
> Hi:
>
> I have a need to interface an Ada library with a C program.
> I am having trouble finding the best way to convert
> strings between the two worlds.
>
> I have a declaration:
>
>     procedure One(Name : in Wide_String);
>     pragma Export(C, One, "one");
>
> When I compile I get:
>
> foo.ads:29:42: warning: type of argument "One" is unconstrained array
> foo.ads:29:42: warning: foreign caller must pass bounds explicitly
>
> Fine, except how do I "pass bounds explicitly" when I call
> this function in C?  The prototype for this function in C
> would normally be:
>
>     void one(wide_string w);
>
> which doesn't have a slot for the bounds.  So where does it
> go?
>
> Alternatively, is there an different way of doing this that
> avoids this problem?
>
> I am using gnat-3.15p.
>
> Thanks,
>
> Paul.
>





^ permalink raw reply	[relevance 7%]

* Re: New to ada, a few questions
  @ 2002-08-06  2:31  5%   ` David C. Hoos, Sr.
  0 siblings, 0 replies; 144+ results
From: David C. Hoos, Sr. @ 2002-08-06  2:31 UTC (permalink / raw)



----- Original Message -----
From: "Keith Thompson" <kst@cts.com>
Newsgroups: comp.lang.ada
To: <comp.lang.ada@ada.eu.org>
Sent: August 05, 2002 6:56 PM
Subject: Re: New to ada, a few questions


> Stephane Jolicoeur <s.jol@jol-tech.net> writes:
> > *** post for FREE via your newsreader at post.newsfeed.com ***
> >
> > Hello,
> > I am a strong python programmer that is looking for a compiled language to
> > complement my tool chest. I tried C but those pointers are an annoyance, I
> > tried C++ but there to the pointers and it's OO weirdness kicked in. Then
I
> > stumbled on an Ada tutorial, I dislike the Pascal-like coding style but
> > there seems to be no pointer and it can be compiled to native byte code !
> >  I would like to know, what good books are there for learning ada ( some
> > sort of tutorial/reference book). How "fast" is compiled Ada code by this
I
> > mean is it like C/C++ or more like Java? I read that it is possible to
> > interface Ada with C? How is this done? Can I use say stdio.h in an Ada
> > program? How about interfacing with C++ or objective C? Are there any GUI
> > librairies (windows, BSD, Mac OS X)? Has any Ada compiler been made to
> > compile code for microcontrollers ( PIC, 68hc11, etc )? How does the
> > threading work? I think this should suffice for a first post.
>
> Ada does have pointers; it calls them access types.  They're not
> needed nearly as often as they are in C.  For example, if you want to
> pass a parameter by reference, you just pass it; there's no need to
> use a pointer type.  Array types are array types.  The bounds of an
> array are fixed when the object is created, but they can be determined
> at run time; again, there's no need to use pointers.  Even when you do
> use pointers, it's much easier to do so safely.  Pointer arithmetic, a
> major source of undefined behavior in C, is not built into the
> language,

If pointer arithic is not built into the language, how do you explain
paragraph B.3.2 (1) which says:

1 The generic package Interfaces.C.Pointers allows the Ada programmer to
perform C-style operations on pointers. It includes an access type Pointer,
Value functions that dereference a Pointer and deliver the designated
array, several pointer arithmetic operations, and �copy� procedures that
copy the contents of a source pointer into the array designated by a
destination pointer. As in C, it treats an object Ptr of type Pointer as a
pointer to the first element of an array, so that for example, adding 1 to
Ptr yields a pointer to the second element of the array.

> and is almost never necessary. <metaphor>Of course you can
> shoot yourself in the foot, but it's harder to do so; the safety is on
> by default and you have to say "I want to turn off the safety now, and
> I know it's dangerous." before you disable it.</metaphor>
>
> No, you can't use <stdio.h> directly (Ada doesn't grok C syntax), but
> Ada does have good facilities for interfacing to other languages, with
> predefined support for C, Fortran, and Cobol, and compiler-specific
> support for C++.  Of course, Ada has its own I/O packages, so there's
> seldom any need to interface to the facilities defined in <stdio.h>.
>
> --
> Keith Thompson (The_Other_Keith) kst@cts.com  <http://www.ghoti.net/~kst>
> San Diego Supercomputer Center           <*>  <http://www.sdsc.edu/~kst>
> Schroedinger does Shakespeare: "To be *and* not to be"
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
>
>





^ permalink raw reply	[relevance 5%]

* Re: Providing C function With Argv
  2002-07-23  8:14  0% ` Ken Thomas
@ 2002-07-24  6:18  0%   ` Jeff
  0 siblings, 0 replies; 144+ results
From: Jeff @ 2002-07-24  6:18 UTC (permalink / raw)


Thanks Ken,

The CArgv and CHelper packages of TASH did the trick.  I only wish I
found them sooner.  It would have saved many hours of hacking in my
feeble attempt to accomplish what I thought should be an "easy" task.
Oh well.  Live and learn.

One bright spot is that I wasn't too far off.  While CArgv and CHelper
are much more elegant, my approach was similar and probably would have
worked with some minor corrections.  However, I decided to use the
CArgv and CHelper packages because they provide functions which should
be helpful in accomplishing my thin port.

Thanks again,

Jeff

"Ken Thomas" <kst@ecs.soton.ac.uk> wrote in message news:<3d3d0fdd@news.ecs.soton.ac.uk>...
> Take a look at the interface to TCL (tash802), there is a package "Cargv"
> that does the job.
> http://unicoi.kennesaw.edu/ase/ase02_02/bindings/tash/
> 
> Ken Thomas
> 
> "Jeff" <jeff.huter@bigfoot.com> wrote in message
> news:fe4bb2c2.0207220726.7502e4bd@posting.google.com...
> > I'm in the process of extending/porting a C program to Ada.  I have an
> > Ada main program that needs to call a C function with the parameters
> > int argc, char **argv.  With Ada.Command_Line, I've been able to pass
> > the C function with int argc.  Using Interfaces.C.Strings, I have even
> > been successful supplying a modified version of the C function with a
> > Interfaces.C.Strings.chars_ptr to provide the function with a single
> > string Argument.  However, I can't seem to figure out how to construct
> > and pass the equivalent of a C char ** in order to pass all the
> > arguments at once.  My guess is that I need to use
> > Interfaces.C.Pointers to construct a Pointer to chars_ptr.  But I've
> > had no luck with this approach.
> >
> > How does one pass a C function the eqivalent of char **?  Is there any
> > easier way to accomplish this than to construct the char **argv from
> > Ada.Command_Line.Argument?  Working code would be much appreciated
> > since I'm rather new to Ada.



^ permalink raw reply	[relevance 0%]

* Re: Providing C function With Argv
  2002-07-22 15:26  5% Providing C function With Argv Jeff
@ 2002-07-23  8:14  0% ` Ken Thomas
  2002-07-24  6:18  0%   ` Jeff
  0 siblings, 1 reply; 144+ results
From: Ken Thomas @ 2002-07-23  8:14 UTC (permalink / raw)


Take a look at the interface to TCL (tash802), there is a package "Cargv"
that does the job.
http://unicoi.kennesaw.edu/ase/ase02_02/bindings/tash/

Ken Thomas

"Jeff" <jeff.huter@bigfoot.com> wrote in message
news:fe4bb2c2.0207220726.7502e4bd@posting.google.com...
> I'm in the process of extending/porting a C program to Ada.  I have an
> Ada main program that needs to call a C function with the parameters
> int argc, char **argv.  With Ada.Command_Line, I've been able to pass
> the C function with int argc.  Using Interfaces.C.Strings, I have even
> been successful supplying a modified version of the C function with a
> Interfaces.C.Strings.chars_ptr to provide the function with a single
> string Argument.  However, I can't seem to figure out how to construct
> and pass the equivalent of a C char ** in order to pass all the
> arguments at once.  My guess is that I need to use
> Interfaces.C.Pointers to construct a Pointer to chars_ptr.  But I've
> had no luck with this approach.
>
> How does one pass a C function the eqivalent of char **?  Is there any
> easier way to accomplish this than to construct the char **argv from
> Ada.Command_Line.Argument?  Working code would be much appreciated
> since I'm rather new to Ada.





^ permalink raw reply	[relevance 0%]

* Providing C function With Argv
@ 2002-07-22 15:26  5% Jeff
  2002-07-23  8:14  0% ` Ken Thomas
  0 siblings, 1 reply; 144+ results
From: Jeff @ 2002-07-22 15:26 UTC (permalink / raw)


I'm in the process of extending/porting a C program to Ada.  I have an
Ada main program that needs to call a C function with the parameters
int argc, char **argv.  With Ada.Command_Line, I've been able to pass
the C function with int argc.  Using Interfaces.C.Strings, I have even
been successful supplying a modified version of the C function with a
Interfaces.C.Strings.chars_ptr to provide the function with a single
string Argument.  However, I can't seem to figure out how to construct
and pass the equivalent of a C char ** in order to pass all the
arguments at once.  My guess is that I need to use
Interfaces.C.Pointers to construct a Pointer to chars_ptr.  But I've
had no luck with this approach.

How does one pass a C function the eqivalent of char **?  Is there any
easier way to accomplish this than to construct the char **argv from
Ada.Command_Line.Argument?  Working code would be much appreciated
since I'm rather new to Ada.



^ permalink raw reply	[relevance 5%]

* Re: newbie inquiry
  @ 2002-06-12 18:09  6%   ` Pascal Obry
  0 siblings, 0 replies; 144+ results
From: Pascal Obry @ 2002-06-12 18:09 UTC (permalink / raw)



Jean-Marc Bourguet <jm@bourguet.org> writes:

> 
> >     * multiple interface inheritence (like Java, m3 doesn't have it)
> 
> No.  AFAIK, there is an extension proposed for normalisation.  Gnat
> has also an extension, I don't know if they are the same.

I don't think the last point is true ! GNAT does not have interface
inheritence.

> 
> >     * fast language interoperability with C (ffi and data sharing)
> Yes

See Interfaces.C, Interfaces.C.Pointers and Interfaces.C.Strings +
pragma Import/Export.

Pascal.

-- 

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|         http://perso.wanadoo.fr/pascal.obry
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595



^ permalink raw reply	[relevance 6%]

* Re: C lib returns char** - How in ADA?
  @ 2002-05-30  7:56  6% ` sk
  0 siblings, 0 replies; 144+ results
From: sk @ 2002-05-30  7:56 UTC (permalink / raw)



Hi, 

I mistakenly hit the send before finishing ...

Have a look at package Interfaces.C.Strings in the
references manual. The package provides :

type char_array_access is access all char_array;
type chars_ptr is private;
type chars_ptr_array is array (size_t range <>) of chars_ptr;

which appears to be what you are looking for.

+++

Then look at Interfaces.C.Pointers.

It gets tricky since you are importing a non-Ada object, but

    package IC  renames Interfaces.C;
    package ICS renames Interfaces.C.Strings;
    package ICP is new Interfaces.C.Pointers (
        Index => IC.Size_t,
        Element => ICS.Chars_Ptr,
        Element_Array => ICS.Chars_Ptr_Array,
        Default_Terminator => ???????
    );

Cannot remember what <???????> should be,

   ICP.Copy_Terminated_Array (...)

should get the foreign data structure into your
application.

Its been a while since I played with this, so details
are fuzzy .. except that I quickly found a hack to
replace the way you are supposed to do it described 
above :-)

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



^ permalink raw reply	[relevance 6%]

* Re: ANN: GMGPL Claw Page
  2002-05-01 16:56  5%   ` Ted Dennison
@ 2002-05-01 18:50  0%     ` Randy Brukardt
  0 siblings, 0 replies; 144+ results
From: Randy Brukardt @ 2002-05-01 18:50 UTC (permalink / raw)


Ted Dennison wrote in message
<4519e058.0205010856.191542a4@posting.google.com>...
>tmoran@acm.org wrote in message
news:<9gBz8.4052$wr1.2380283950@newssvr21.news.prodigy.com>...
>>   Claw uses 'access', not system.address, which is not, in fact,
always
>> the same thing as a C pointer.
>
>Right. I seem to rememer a discussion here a long time ago, where the
>general conclusion was that, while in theory there is no guarantee
>System.Adress is implemented in any specific way, in practice
>System.Address is more likely to match up with a C pointer than an
>access type is.


No, that's wrong. If you want a C pointer in your Ada program, all you
need to do is declare one:

    type Access_Whatever is access Whatever;
    pragma Convention (C, Access_Whatever);

If a compiler accepts this and doesn't give you an access type
compatible with a C pointer, you've got a seriously buggy compiler! Best
find a different one. A compiler might reject it, depending on what
Whatever is, but that generally doesn't happen.

One a few targets (like the Unisys 2200 compiler we did), Ada accesses
and C pointers don't have the same representation. (C pointers are bit
pointers on that machine, and we didn't want to pay for that when we
didn't need it in Ada.)

>I think the only place I ever use it any more is in bindings (where
>you are generally at a icky low level anyway). However, I'd have to
>check my code to see exactly where it is used. I know I'm rather
>liberal with Addresses on unused pointer parameters, but I can't
>remember how I was doing *used* pointer parameters. I'm pretty sure I
>don't make much use of Interfaces.C.Pointers. Perhaps that's a bad
>move?


No, using the above is just as good. Just be sure to (somehow) declare
that you want a C pointer. As far as "unused" pointer parameters go, we
just use Claw.DWord for that on Claw. That is the right size, and
portability to another OS is not an issue for Claw.

>Anyway, the possible issues with System.Address is why I mentioned it.
>I'm certianly willing to learn the proper portable way to get at C
>pointers, and from the looks of things, the folks who wrote Claw would
>know a thing or two about portability. :-)


At least between Windows platform compilers...

          Randy.






^ permalink raw reply	[relevance 0%]

* Re: ANN: GMGPL Claw Page
  2002-04-30 18:20  5% ` tmoran
@ 2002-05-01 16:56  5%   ` Ted Dennison
  2002-05-01 18:50  0%     ` Randy Brukardt
  0 siblings, 1 reply; 144+ results
From: Ted Dennison @ 2002-05-01 16:56 UTC (permalink / raw)


tmoran@acm.org wrote in message news:<9gBz8.4052$wr1.2380283950@newssvr21.news.prodigy.com>...
>   Claw uses 'access', not system.address, which is not, in fact, always
> the same thing as a C pointer.

Right. I seem to rememer a discussion here a long time ago, where the
general conclusion was that, while in theory there is no guarantee
System.Adress is implemented in any specific way, in practice
System.Address is more likely to match up with a C pointer than an
access type is.

>   I really can't understand why, given the examples of
> System.Address_To_Access_Conversions, Interfaces.C.Strings,
> Interfaces.C.Pointers, and a given a demonstrated ability to move
> comfortably among different abstractions, anyone would use such a low
> level, implementation defined thing as System.Address.  Given the
> frequency with which it's done in c.l.a. postings, I guess it seems
> reasonable to more than a few people.  #.#

I think the only place I ever use it any more is in bindings (where
you are generally at a icky low level anyway). However, I'd have to
check my code to see exactly where it is used. I know I'm rather
liberal with Addresses on unused pointer parameters, but I can't
remember how I was doing *used* pointer parameters. I'm pretty sure I
don't make much use of Interfaces.C.Pointers. Perhaps that's a bad
move?

Anyway, the possible issues with System.Address is why I mentioned it.
I'm certianly willing to learn the proper portable way to get at C
pointers, and from the looks of things, the folks who wrote Claw would
know a thing or two about portability. :-)


-- 
T.E.D. 
Home     -  mailto:dennison@telepath.com (Yahoo: Ted_Dennison)
Homepage -  http://www.telepath.com/dennison/Ted/TED.html



^ permalink raw reply	[relevance 5%]

* Re: ANN: GMGPL Claw Page
  @ 2002-04-30 18:20  5% ` tmoran
  2002-05-01 16:56  5%   ` Ted Dennison
  0 siblings, 1 reply; 144+ results
From: tmoran @ 2002-04-30 18:20 UTC (permalink / raw)


> portability issues are confied to:
>
> o  Using a particular convention name (eg: "stdcall") that may not
> exist on other compilers. (The only predefined one is "C", which is
> not what a lot of Win32 uses).
> o  Assuming Ada's Address type is compatable with C pointers.
  "stdcall" is already used in Claw.  It works on Apex, Gnat, ObjectAda,
and Janus.
  Claw uses 'access', not system.address, which is not, in fact, always
the same thing as a C pointer.

  I really can't understand why, given the examples of
System.Address_To_Access_Conversions, Interfaces.C.Strings,
Interfaces.C.Pointers, and a given a demonstrated ability to move
comfortably among different abstractions, anyone would use such a low
level, implementation defined thing as System.Address.  Given the
frequency with which it's done in c.l.a. postings, I guess it seems
reasonable to more than a few people.  #.#



^ permalink raw reply	[relevance 5%]

* Re: C++ binding
  @ 2002-04-25 18:32  6% ` Pascal Obry
  0 siblings, 0 replies; 144+ results
From: Pascal Obry @ 2002-04-25 18:32 UTC (permalink / raw)



Dominique Devriese <fritmebufstek@pandora.be> writes:

> Hi, i'm completely new to Ada, but i'm considering learning it...
> What i would like to know however, is if it is possible to use C++ or
> C libraries in Ada programs, since most of my programming work
> requires using those library's.  Can anyone give me some pointers
> on where to find information about this ?
> domi

Yes it is possible. Ada has a special annexe for interfacing to other
languages. See Annexe B in the Ada Reference Manual. Look at the Interfaces.C,
Interfaces.C.Strings and Interfaces.C.Pointers pacakges. Note that Ada has
also interfaces API for Fortran and COBOL.

Pascal.

-- 

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|         http://perso.wanadoo.fr/pascal.obry
--|
--| "The best way to travel is by means of imagination"



^ permalink raw reply	[relevance 6%]

* Interfacing Ada95 to C++ - Object passing problem
@ 2002-04-25 11:44  3% Markus Knauss
  0 siblings, 0 replies; 144+ results
From: Markus Knauss @ 2002-04-25 11:44 UTC (permalink / raw)


Hello,

I'm going to use Ada95 libraries in C++. During evaluation of the Ada
interfacing capabilities I found an interessting problem when passing
objects.

I hope that anybody knows about the described problem and can me tell
where I made an error.

First I will introduce snippets of the sources and then describe the
problem and its solution.

The body and spec of the Ada implementation defines a class with a
single attribute. The attribute is an unbounded_string. The attribute
of an object of this class can be set with the "set" method. Below
excerpts from the spec and body file:

<snip (spec-file)>
type s_type is record
  name : ada.strings.unbounded.unbounded_string;
end record;
pragma convention (c, s_type);
type s_obj is access s_type;
<snap>

<snip (body-file)>
function create
  return s_obj is
begin
  return new s_type;
end create;

procedure set (obj : in out s_obj; name : string) is
begin
  obj.name := to_unbounded_string (name);
end set;
procedure set_c (obj : in out s_obj; name :
interfaces.c.pointers.chars_ptr) is
begin
  set (obj, value (name));
end set_c;
pragma export (c, set_c, "set");
<snap>
The class and the exported function is reflected in a C-Header file.
The class and function is accessed from a C++ main. Below are excerpts
of the header and the main file.

<snip (header file)>
struct s_type {};
typedef s_type* s_obj;
extern "C" s_obj create();
extern "C" void set(s_obj obj, char* name);
<snap>

<snip (file including main)>
extern "C" void adainit();
int main(int argc, char** argv) {
  adainit();
  s_obj obj = create();  set(obj, "Hello world!");
}
<snap>
The sources were compiled using gnat 3.13p and gcc 2.95.3.

Now the problem: When converting the string to an unbounded string, in
the set procedure, the program crashes with an segmentation fault. To
this point everything works fine. When omitting the attributes "in
out" to the obj parameter in the procedures set_c and set everything
works fine.

As I investigated, the Segmentation fault occurs when freeing some
memory in the implementation of To_Unbounded_String. I tested the same
implementation with Bounded_Strings and the result was: If using 'in
out' attributes for obj, the objects attribute was empty but
assignment and conversion worked. Omitting the 'in out' attributes
everything worked fine.

Does anyone know about this or knows why the attributes 'in out' must
be omitted?

Thanks for your answers,
  Markus



^ permalink raw reply	[relevance 3%]

* Re: List Container Strawman 1.4
  2001-12-28 19:49  3%       ` Matthew Heaney
@ 2001-12-29 23:23  0%         ` Matthew Heaney
  0 siblings, 0 replies; 144+ results
From: Matthew Heaney @ 2001-12-29 23:23 UTC (permalink / raw)



"Matthew Heaney" <mheaney@on2.com> wrote in message
news:u2pitjhps1bp07@corp.supernews.com...
> If you wanted, you could generalize this further (as the STL does) to
> abstract away the target type (in the example above we've hard-coded an
> array type as the target type).  To do this for arrays you'd need an
> appropriate iterator type; maybe Interfaces.C.Pointers would work.

In the example below I wrote an array iterator and a Generic_Copy algorithm
that works for any target type.  The basic idea is:

declare
   ...
    procedure Copy is
         new Generic_Copy
           (Integer_Lists.Iterator_Type,
            Integer_Arrays.Iterator_Type);

      Items : aliased Integer_Array (1 .. Length (List));
      Iter : Integer_Arrays.Iterator_Type := Items
(Items'First)'Unchecked_Access;
   begin
      Copy (First (List), Back (List), Iter);
  end;

This is exactly how the STL does things.

The code below is suitable for use with gnatchop.

--STX
with System.Storage_Elements;
with Ada.Unchecked_Conversion;

package body Array_Iterators is

   use type System.Storage_Elements.Storage_Offset;


   function To_Iterator is
      new Ada.Unchecked_Conversion (System.Address, Iterator_Type);

   function First (Items : access Array_Type) return Iterator_Type is
   begin
      return Items (Items'First)'Access;
   end;


   function Back (Items : access Array_Type) return Iterator_Type is

      First_Address : constant System.Address := Items
(Items'First)'Address;

      Length : constant System.Storage_Elements.Storage_Count :=
Items'Length;

      Offset : constant System.Storage_Elements.Storage_Count :=
         Length * Array_Type'Component_Size / System.Storage_Unit;

      Back_Address : constant System.Address := First_Address + Offset;

   begin

      return To_Iterator (Back_Address);

   end;


   function Item (Iterator : Iterator_Type) return Item_Type is
   begin
      return Iterator.all;
   end;


   procedure Next (Iterator : in out Iterator_Type) is

      Curr_Address : constant System.Address := Iterator.all'Address;

      Offset : constant System.Storage_Elements.Storage_Count :=
         Array_Type'Component_Size / System.Storage_Unit;

      Next_Address : constant System.Address := Curr_Address + Offset;

   begin

      Iterator := To_Iterator (Next_Address);

   end;


end Array_Iterators;
generic

   type Item_Type is limited private;

   type Index_Type is range <>;

   type Array_Type is array (Index_Type range <>) of aliased Item_Type;

package Array_Iterators is

   type Iterator_Type is access all Item_Type;
   for Iterator_Type'Storage_Size use 0;

   function First (Items : access Array_Type) return Iterator_Type;

   function Back (Items : access Array_Type) return Iterator_Type;

   function Item (Iterator : Iterator_Type) return Item_Type;

   procedure Next (Iterator : in out Iterator_Type);

end Array_Iterators;

      procedure Generic_Copy
  (First  : in     Source_Iterator_Type;
   Back   : in     Source_Iterator_Type;
   Target : in out Target_Iterator_Type) is

   Source : Source_Iterator_Type := First;
begin
   while Source /= Back loop
      Set_Item (Source, Target);
      Next (Source);
      Next (Target);
   end loop;
end Generic_Copy;

generic

   type Source_Iterator_Type (<>) is private;

   type Target_Iterator_Type (<>) is private;

   with procedure Set_Item
     (Source : Source_Iterator_Type;
      Target : Target_Iterator_Type) is <>;

   with procedure Next (Iterator : in out Source_Iterator_Type) is <>;

   with procedure Next (Iterator : in out Target_Iterator_Type) is <>;

   with function "=" (L, R : Source_Iterator_Type) return Boolean is <>;

procedure Generic_Copy
  (First  : in     Source_Iterator_Type;
   Back   : in     Source_Iterator_Type;
   Target : in out Target_Iterator_Type);
   with Array_Iterators;
pragma Elaborate_All (Array_Iterators);

package Integer_Arrays is

   type Integer_Array is array (Positive range <>) of aliased Integer;

   package Integer_Array_Iterators is
      new Array_Iterators (Integer, Positive, Integer_Array);

   type Iterator_Type is new Integer_Array_Iterators.Iterator_Type;

end Integer_Arrays;
with Unbounded_Lists;
pragma Elaborate_All (Unbounded_Lists);

package Integer_Lists is
   new Unbounded_Lists (Integer);

with Integer_Lists;  use Integer_Lists;
with Integer_Arrays;  use Integer_Arrays;
with Generic_Copy;
with Ada.Text_IO;  use Ada.Text_IO;
with Ada.Integer_Text_IO;  use Ada.Integer_Text_IO;

procedure Test_Copy is

   List : List_Type;

begin

   for I in 1 .. 5 loop
      Push_Back (List, I);
   end loop;

   declare
      Iter : Integer_Lists.Iterator_Type := First (List);
      Back : constant Integer_Lists.Iterator_Type := Integer_Lists.Back
(List);
   begin
      Put ("source:");

      while Iter /= Back loop
         Put (' ');
         Put (Item (Iter), Width => 0);
         Next (Iter);
      end loop;

      New_Line;
   end;

   declare
      procedure Set_Item
        (Source : Integer_Lists.Iterator_Type;
         Target : Integer_Arrays.Iterator_Type) is
      begin
         Target.all := Item (Source);
      end;

      pragma Warnings (Off, Set_Item);

      procedure Copy is
         new Generic_Copy
           (Integer_Lists.Iterator_Type,
            Integer_Arrays.Iterator_Type);

      Items : aliased Integer_Array (1 .. Length (List));
      Iter : Integer_Arrays.Iterator_Type := Items
(Items'First)'Unchecked_Access;
   begin
      Copy (First (List), Back (List), Iter);

      Put ("target:");

      for I in Items'Range loop
         Put (' ');
         Put (Items (I), Width => 0);
      end loop;

      New_Line;
   end;


end Test_Copy;

with Ada.Unchecked_Deallocation;  --should pass in storage_pool

package body Unbounded_Lists is

   procedure Free is
      new Ada.Unchecked_Deallocation (Node_Type, Node_Access);


   procedure Initialize (List : in out List_Type) is
   begin

      List.Front := new Node_Type;
      List.Back := new Node_Type;

      List.Front.Next := List.Back;
      List.Back.Prev := List.Front;

      List.Length := 0;

   end Initialize;


   procedure Finalize (List : in out List_Type) is
   begin
      Clear (List);
      Free (List.Front);
      Free (List.Back);
   end;


   procedure Push_Front
     (List : in out List_Type;
      Item : in     Item_Type) is

      Node : constant Node_Access :=
         new Node_Type'(Item => Item,
                        Next => List.Front.Next,
                        Prev => List.Front);
   begin
      Node.Next.Prev := Node;
      List.Front.Next := Node;
      List.Length := List.Length + 1;
   end;


   procedure Push_Front
     (List : access List_Type;
      Item : in     Item_Type) is
   begin
      Push_Front (List.all, Item);
   end;


   procedure Push_Back
     (List : in out List_Type;
      Item : in     Item_Type) is

      Node : constant Node_Access :=
         new Node_Type'(Item => Item,
                        Next => List.Back,
                        Prev => List.Back.Prev);
   begin
      Node.Prev.Next := Node;
      List.Back.Prev := Node;
      List.Length := List.Length + 1;
   end;


   procedure Push_Back
     (List : access List_Type;
      Item : in     Item_Type) is
   begin
      Push_Back (List.all, Item);
   end;


   procedure Push_Front (List : in out List_Type) is
      Node : constant Node_Access := new Node_Type;
   begin
      Node.Next := List.Front.Next;
      Node.Prev := List.Front;
      Node.Next.Prev := Node;
      List.Front.Next := Node;
      List.Length := List.Length + 1;
   end;


   procedure Push_Back (List : in out List_Type) is
      Node : constant Node_Access := new Node_Type;
   begin
      Node.Next := List.Back;
      Node.Prev := List.Back.Prev;
      Node.Prev.Next := Node;
      List.Back.Prev := Node;
      List.Length := List.Length + 1;
   end;


   procedure Pop_Front (List : in out List_Type) is
      pragma Assert (List.Length > 0);

      Node : Node_Access := List.Front.Next;
   begin
      List.Front.Next := Node.Next;
      Node.Next.Prev := List.Front;
      List.Length := List.Length - 1;
      Free (Node);
   end;

   procedure Pop_Back (List : in out List_Type) is
      pragma Assert (List.Length > 0);

      Node : Node_Access := List.Back.Prev;
   begin
      List.Back.Prev := Node.Prev;
      Node.Prev.Next := List.Back;
      List.Length := List.Length - 1;
      Free (Node);
   end;


   function Length (List : List_Type) return Natural is
   begin
      return List.Length;
   end;


   procedure Clear (List : in out List_Type) is
      Node : Node_Access := List.Front.Next;
      Next : Node_Access;
   begin
      while Node /= List.Back loop
         Next := Node.Next;
         Free (Node);
         Node := Next;
      end loop;

      List.Front.Next := List.Back;
      List.Back.Prev := List.Front;
      List.Length := 0;
   end;


   function First (List : List_Type) return Item_Type is
      pragma Assert (List.Length > 0);
   begin
      return List.Front.Next.Item;
   end;

   function Last (List : List_Type) return Item_Type is
      pragma Assert (List.Length > 0);
   begin
      return List.Back.Prev.Item;
   end;

   procedure Swap (L, R : in out List_Type) is
      Front : constant Node_Access := L.Front;
      Back  : constant Node_Access := L.Back;
      Length : constant Natural := L.Length;
   begin
      L.Front := R.Front;
      L.Back := R.Back;
      L.Length := R.Length;

      R.Front := Front;
      R.Back := Back;
      R.Length := Length;
   end;



   function First (List : List_Type) return Iterator_Type is
      pragma Assert (List.Length > 0);
   begin
      return Iterator_Type'(Node => List.Front.Next);
   end;

   function Last (List : List_Type) return Iterator_Type is
      pragma Assert (List.Length > 0);
   begin
      return Iterator_Type'(Node => List.Back.Prev);
   end;

   function Front (List : List_Type) return Iterator_Type is
   begin
      return Iterator_Type'(Node => List.Front);
   end;

   function Back (List : List_Type) return Iterator_Type is
   begin
      return Iterator_Type'(Node => List.Back);
   end;

   procedure Next (Iterator : in out Iterator_Type) is
   begin
      Iterator.Node := Iterator.Node.Next;
   end;

   procedure Previous (Iterator : in out Iterator_Type) is
   begin
      Iterator.Node := Iterator.Node.Prev;
   end;

   function Item (Iterator : Iterator_Type) return Item_Type is
   begin
      return Iterator.Node.Item;
   end;


end Unbounded_Lists;
with Ada.Finalization;

generic

   type Item_Type is private;

package Unbounded_Lists is

   type List_Type is limited private;


   procedure Push_Front
     (List : in out List_Type;
      Item : in     Item_Type);

   procedure Push_Front
     (List : access List_Type;
      Item : in     Item_Type);

   procedure Push_Front (List : in out List_Type);

   procedure Pop_Front (List : in out List_Type);


   procedure Push_Back
     (List : in out List_Type;
      Item : in     Item_Type);

   procedure Push_Back
     (List : access List_Type;
      Item : in     Item_Type);

   procedure Push_Back (List : in out List_Type);

   procedure Pop_Back (List : in out List_Type);



   function Length (List : List_Type) return Natural;

   procedure Clear (List : in out List_Type);

   function First (List : List_Type) return Item_Type;

   function Last (List : List_Type) return Item_Type;

   procedure Swap (L, R : in out List_Type);


   type Iterator_Type is private;

   function First (List : List_Type) return Iterator_Type;

   function Last (List : List_Type) return Iterator_Type;

   function Front (List : List_Type) return Iterator_Type;

   function Back (List : List_Type) return Iterator_Type;

   procedure Next (Iterator : in out Iterator_Type);

   procedure Previous (Iterator : in out Iterator_Type);

   function Item (Iterator : Iterator_Type) return Item_Type;


private

   type Node_Type;
   type Node_Access is access Node_Type;

   type Node_Type is
      record
         Item : aliased Item_Type;
         Next : Node_Access;
         Prev : Node_Access;
      end record;

   type Handle_Type (L : access List_Type) is limited null record;

   type List_Type is
      new Ada.Finalization.Limited_Controlled with record
         H      : Handle_Type (List_Type'Access);
         Front  : Node_Access;
         Back   : Node_Access;
         Length : Natural;
      end record;

   procedure Initialize (List : in out List_Type);
   procedure Finalize (List : in out List_Type);

   type Iterator_Type is
      record
         Node : Node_Access;
      end record;

end Unbounded_Lists;






^ permalink raw reply	[relevance 0%]

* Re: List Container Strawman 1.4
  @ 2001-12-28 19:49  3%       ` Matthew Heaney
  2001-12-29 23:23  0%         ` Matthew Heaney
  0 siblings, 1 reply; 144+ results
From: Matthew Heaney @ 2001-12-28 19:49 UTC (permalink / raw)



"Hyman Rosen" <hyrosen@mail.com> wrote in message
news:3C2CA143.6030006@mail.com...
> Ted Dennison wrote:
>
> > Actually, I was thinking along the lines of an Containers.Lists.Fixed
>
>  > package that works with arrays.
>
> I think this kind of thing is where C++'s iterators and algorithms
> approach shows its superiority. Why should a List have any notion
> of other data structures to which its elements can be copied?

You're right, it shouldn't.  Iterators allow you to abstract away the
differences among different containers.  That's the whole point.

The app I will be submitting to the Ada-Belgium competition includes a list
container type that allows you to copy its items using iterators, like this:

List : Integer_Lists.List_Type;
...
declare
   Items : array (1 .. Length (List)) of Integer;
   Iter : Iterator_Type := First (List);
begin
   for I in Items'Range loop
      Items (I) := Item (Iter);
      Next (Iter);
   end loop;
end;

(My list type has selectors that return iterators designating First, Last,
Front, and Back.  The latter two are sentinals.)

It would be easy to generalize this algorithm to copy items from any
container type with an iterator:

generic
   type Iterator_Type (<>) is private;
   type Item_Type is private;
   type Item_Array is array (Positive range <>) of Item_Type;
   with function "=" (L, R : Iterator_Type) return Boolean is <>;
procedure Generic_Copy
  (First  : in      Iterator_Type;
   Back : in      Iterator_Type;
   Items : in out Items_Type);

procedure Generic_Copy (...) is
   Iter : Iterator_Type := First;
   I : Positive := Items'First;
begin
   while Iter /= Back loop
      Items (I) := Item (Iter);
      Next (Iter);
      I := I + 1;
   end loop;
end Generic_Copy;

If you wanted, you could generalize this further (as the STL does) to
abstract away the target type (in the example above we've hard-coded an
array type as the target type).  To do this for arrays you'd need an
appropriate iterator type; maybe Interfaces.C.Pointers would work.









^ permalink raw reply	[relevance 3%]

* Re: Ada Address = C pointer ?
  2001-10-30 19:53  0% ` tmoran
@ 2001-10-31 13:01  0%   ` M. A. Alves
  0 siblings, 0 replies; 144+ results
From: M. A. Alves @ 2001-10-31 13:01 UTC (permalink / raw)
  To: comp.lang.ada

On Tue, 30 Oct 2001 tmoran@acm.org wrote:
> . . .
>
> > So, either way (Interfaces.C.Pointers vs.
> > System.Address_To_Access_Conversions), _assumptions_ are made (by the
> > programmer).
>
> . . . Does the RM even suggest that a System.Address has anything to
> do with interfacing to other languages?

Hmmm... touch�.

> . . .
>
>   In the meantime, put in a comment for future maintainers that
> your code assumes a specific Gnat version on a specific platform.

Something like that, yes.

> . . .

Thanks,

-- 
   ,
 M A R I O   data miner, LIACC, room 221   tel 351+226078830, ext 121
 A M A D O   Rua Campo Alegre, 823         fax 351+226003654
 A L V E S   P-4150 PORTO, Portugal        mob 351+939354002





^ permalink raw reply	[relevance 0%]

* Re: Ada Address = C pointer ?
  @ 2001-10-30 19:53  0% ` tmoran
  2001-10-31 13:01  0%   ` M. A. Alves
  0 siblings, 1 reply; 144+ results
From: tmoran @ 2001-10-30 19:53 UTC (permalink / raw)


> Interesting. The code is incompatible with GNAT.
  Of course it is.  The particular Gnat you are using has a System.Address
that only works within a single segment, so it does not include the
segment part.  The ARM suggests System.Address should be private,
presumably to discourage coding that depends on a particular
implementation.

> Ada                C
> --------------------
> Address       * void
> Address       * char
> Null_Address    NULL
>
> GNAT seems to honor these equivalences.  Does Janus?
  (I'm not sure I'd use the word "honor" to describe a particular
implementation artifact. ;)
  I haven't used any Janus compilers on other platforms, so can't answer
for them.  On x86's Janus appears to convert (I haven't experimented with this
since I use Access types) automagically on parameter passing, but I'm sure

  type Address_List is array(1 .. 10) of System.Address;
  X : Address_List;
  procedure Cfunc(X : out Address_List);
  pragma Import(C, Cfunc);
---
  void Cfunc(char **p)

would give unpleasant results.

Do all versions of Gnat on all platforms implement those particular
equivalences?  Do even all other Ada compilers on your current platform
implement them?

> Yes, I know that null = NULL seems an obvious interpretation of
> "C-compatible", but the RM is not known for relying on the obvious.
>
> So, either way (Interfaces.C.Pointers vs.
> System.Address_To_Access_Conversions), _assumptions_ are made (by the
> programmer).
  Can you suggest any other reasonable interpretation besides null = NULL?
Does the RM even suggest that a System.Address has anything to do with
interfacing to other languages?  The RM may not be obvious, but it doesn't
*try* to mislead.

> But I agree a Pointers idiom is a viable, perhaps better, alternative to a
> System one. Perhaps I'll change my code some day.
  In the meantime, put in a comment for future maintainers that
your code assumes a specific Gnat version on a specific platform.
(Having maintained code dependent on a particular, ancient, version of
a compiler, I offer my condolences to those maintainers.)



^ permalink raw reply	[relevance 0%]

* Re: Ada Address = C pointer ?
  2001-10-30 17:10  0%   ` Mark Johnson
@ 2001-10-30 18:01  4%     ` M. A. Alves
  0 siblings, 0 replies; 144+ results
From: M. A. Alves @ 2001-10-30 18:01 UTC (permalink / raw)
  To: comp.lang.ada

On Tue, 30 Oct 2001, Mark Johnson wrote:
> "M. A. Alves" wrote:
> > I am in fact using Address and Access_To_Address_Conversions(*) because I
> > simply did not find out how to do the trick otherwise.  For example, the C
> > function is returning an array of unsigned long.  I want to access that
> > array without copying it.  How can you do that with Interfaces.C.Strings
> > or even Interfaces.C.Pointers ?
>
> Reread the implementation advice in B.3....
>  An Ada parameter of an array type with component type T, of any mode, is passed
> as a t* argument to a C function, where t is the C type corresponding to the Ada
> type T.

Yes, a very sensible _advice_ indeed. Somehow I feel more assured with
Address_To_Access_Conversions. Actually it is more than just a feeling,
according to http://adapower.com/lang/accessmem.html .

But adhering to the advice surely makes for the most elegant coding.

Note that by now, thanks to all, this thread has tutored all possible
idioms of C-interfacing namely:

  * using Address_To_Access_Conversions

  * using Interfaces.C.Pointers

  * commiting to implementation advice in B.3...

Well done guys!

-- 
   ,
 M A R I O   data miner, LIACC, room 221   tel 351+226078830, ext 121
 A M A D O   Rua Campo Alegre, 823         fax 351+226003654
 A L V E S   P-4150 PORTO, Portugal        mob 351+939354002





^ permalink raw reply	[relevance 4%]

* Re: Ada Address = C pointer ?
  2001-10-30  9:58  5% ` M. A. Alves
  2001-10-30 12:02  7%   ` Lutz Donnerhacke
@ 2001-10-30 17:10  0%   ` Mark Johnson
  2001-10-30 18:01  4%     ` M. A. Alves
  1 sibling, 1 reply; 144+ results
From: Mark Johnson @ 2001-10-30 17:10 UTC (permalink / raw)


"M. A. Alves" wrote:

> [snip]

> I am in fact using Address and Access_To_Address_Conversions(*) because I
> simply did not find out how to do the trick otherwise.  For example, the C
> function is returning an array of unsigned long.  I want to access that
> array without copying it.  How can you do that with Interfaces.C.Strings
> or even Interfaces.C.Pointers ?
>

Reread the implementation advice in B.3....
 An Ada parameter of an array type with component type T, of any mode, is passed
as a t* argument to a C function, where t is the C type corresponding to the Ada
type T.

Of course, your mileage may vary - but here's a simple test case that I ran using
GNAT on Linux....

a.c...
#include <string.h>
void a ( int * x, int * y) {
  memcpy(y, x, 40);
}
b.adb...
with Text_Io;
procedure B is
  type Xt is array (1..10) of Integer;
  Y : Xt := (others => 1);
  Z : Xt := (others => 0);

  procedure A (X : Xt; Y : Xt);
  pragma Import(C, A, "a");

  begin
  A(Y, Z);
  if (Z(1)=1) then
    Text_Io.Put_Line("Ok");
  else
    Text_Io.Put_Line("Failed");
  end if;
end B;

which after being built runs and prints out "Ok".

Good luck.
  --Mark




^ permalink raw reply	[relevance 0%]

* Re: Ada Address = C pointer ?
  @ 2001-10-30 14:41  5% ` M. A. Alves
  0 siblings, 0 replies; 144+ results
From: M. A. Alves @ 2001-10-30 14:41 UTC (permalink / raw)
  To: comp.lang.ada

On Tue, 30 Oct 2001, Matthew Heaney wrote:
> "M. A. Alves" <maa@liacc.up.pt> wrote in message
> news:mailman.1004446456.21280.comp.lang.ada@ada.eu.org...
> > However, I am still not sure of the equivalence between null (a value of
> > Pointer) and NULL (C), i.e. is it garanteed that if the C function returns
> > NULL get_long_array returns null?
>
> Yes.  See RM95 B3.2 (17).

Yes, I know that null = NULL seems an obvious interpretation of
"C-compatible", but the RM is not known for relying on the obvious.

So, either way (Interfaces.C.Pointers vs.
System.Address_To_Access_Conversions), _assumptions_ are made (by the
programmer).

But I agree a Pointers idiom is a viable, perhaps better, alternative to a
System one. Perhaps I'll change my code some day.

-- 
   ,
 M A R I O   data miner, LIACC, room 221   tel 351+226078830, ext 121
 A M A D O   Rua Campo Alegre, 823         fax 351+226003654
 A L V E S   P-4150 PORTO, Portugal        mob 351+939354002





^ permalink raw reply	[relevance 5%]

* Re: Ada Address = C pointer ?
  2001-10-30 12:02  7%   ` Lutz Donnerhacke
@ 2001-10-30 12:53  0%     ` M. A. Alves
  0 siblings, 0 replies; 144+ results
From: M. A. Alves @ 2001-10-30 12:53 UTC (permalink / raw)
  To: comp.lang.ada

On Tue, 30 Oct 2001, Lutz Donnerhacke wrote:
> How about:
>
> with Interfaces.C.Pointers;
>
> procedure t is
>    type long_array is array (Integer range <>) of aliased Interfaces.C.long;
>
>    package long_pointers is new Interfaces.C.Pointers (
>      Index              => Integer,
>      Element            => Interfaces.C.long,
>      Element_Array      => long_array,
>      Default_Terminator => 0
>    );
>
>    function get (a : long_pointers.Pointer; i : Interfaces.C.ptrdiff_t)
>      return Interfaces.C.long is
>
>       use type long_pointers.Pointer;
>
>       v : long_array (1 .. 1) :=
>         long_pointers.Value (a + i, Interfaces.C.ptrdiff_t (1));
>    begin
>       return v (1);
>    end get;
>    pragma Inline (get);
>
>    --  real work starts here
>
>    function get_long_array return long_pointers.Pointer;
>    pragma Import (C, get_long_array);
>
>    my_array : constant long_pointers.Pointer := get_long_array;
> begin
>    ... := get (my_array, 4);
> end t;

Seems right.  The C.Pointers tutorial I was missing, thanks a lot.

However, I am still not sure of the equivalence between null (a value of
Pointer) and NULL (C), i.e. is it garanteed that if the C function returns
NULL get_long_array returns null?

-- 
   ,
 M A R I O   data miner, LIACC, room 221   tel 351+226078830, ext 121
 A M A D O   Rua Campo Alegre, 823         fax 351+226003654
 A L V E S   P-4150 PORTO, Portugal        mob 351+939354002





^ permalink raw reply	[relevance 0%]

* Re: Ada Address = C pointer ?
  2001-10-30  9:58  5% ` M. A. Alves
@ 2001-10-30 12:02  7%   ` Lutz Donnerhacke
  2001-10-30 12:53  0%     ` M. A. Alves
  2001-10-30 17:10  0%   ` Mark Johnson
  1 sibling, 1 reply; 144+ results
From: Lutz Donnerhacke @ 2001-10-30 12:02 UTC (permalink / raw)


* M. A. Alves wrote:
>I am in fact using Address and Access_To_Address_Conversions(*) because I
>simply did not find out how to do the trick otherwise.  For example, the C
>function is returning an array of unsigned long.  I want to access that
>array without copying it.  How can you do that with Interfaces.C.Strings
>or even Interfaces.C.Pointers?

How about:

with Interfaces.C.Pointers;

procedure t is
   type long_array is array (Integer range <>) of aliased Interfaces.C.long;
   
   package long_pointers is new Interfaces.C.Pointers (
     Index              => Integer,
     Element            => Interfaces.C.long,
     Element_Array      => long_array,
     Default_Terminator => 0
   );
   
   function get (a : long_pointers.Pointer; i : Interfaces.C.ptrdiff_t)
     return Interfaces.C.long is
     
      use type long_pointers.Pointer;
      
      v : long_array (1 .. 1) :=
        long_pointers.Value (a + i, Interfaces.C.ptrdiff_t (1));
   begin
      return v (1);
   end get;
   pragma Inline (get);
   
   --  real work starts here
   
   function get_long_array return long_pointers.Pointer;
   pragma Import (C, get_long_array);
   
   my_array : constant long_pointers.Pointer := get_long_array;
begin
   ... := get (my_array, 4);
end t;




^ permalink raw reply	[relevance 7%]

* Re: Ada Address = C pointer ?
  @ 2001-10-30  9:58  5% ` M. A. Alves
  2001-10-30 12:02  7%   ` Lutz Donnerhacke
  2001-10-30 17:10  0%   ` Mark Johnson
  0 siblings, 2 replies; 144+ results
From: M. A. Alves @ 2001-10-30  9:58 UTC (permalink / raw)
  To: comp.lang.ada

On Mon, 29 Oct 2001, Matthew Heaney wrote:
> "M. A. Alves" <maa@liacc.up.pt> wrote in message
> news:mailman.1004357020.21840.comp.lang.ada@ada.eu.org...
> > You mean use Address_To_Access conversion?  Because what I have is C
> > pointers I need to interface with.  I am using Chars_Ptr because it has a
> > Null_Ptr value and I need to test for, and pass, NULL.  (And in C char *
> > is assuredly able to point to anything.)  But I am indeed considering
> > using Address et al., and Address to Access conversion.
>
> . . .
>
> I do NOT think you need to use System.Address and Addr_To_Acc_Conv.  The
> types declared in C.Strings should be adequate.

I am in fact using Address and Access_To_Address_Conversions(*) because I
simply did not find out how to do the trick otherwise.  For example, the C
function is returning an array of unsigned long.  I want to access that
array without copying it.  How can you do that with Interfaces.C.Strings
or even Interfaces.C.Pointers ?

Also, I did not found the equivalence Null_Ptr = NULL stated in the RM.

> That being said, I would be very surprised if System.Address had a
> different representation from char* or void*.

Yes, and for now my implementation is bound to that assumption.
_____
(*) I am using a technique similar to the one referenced as 2c in
"Accessing Memory as a String" by Robert Dewar, available at
adapower.com/lang/accessmem.html .

-- 
   ,
 M A R I O   data miner, LIACC, room 221   tel 351+226078830, ext 121
 A M A D O   Rua Campo Alegre, 823         fax 351+226003654
 A L V E S   P-4150 PORTO, Portugal        mob 351+939354002






^ permalink raw reply	[relevance 5%]

* Possible Bug, Need Second Opinion
@ 2001-09-23 18:01  7% ANH_VO
  0 siblings, 0 replies; 144+ results
From: ANH_VO @ 2001-09-23 18:01 UTC (permalink / raw)
  To: comp.lang.ada

I am nearly 100% certain that the codes below should compile fine. But, I would
like to have second opinion possibly more before reporting it.

with Interfaces;

package Global is

   type Size_T is new Interfaces.Unsigned_32;

end Global;


with Global;
with Interfaces.C.Pointers;

package Index_Rejection is

   use Global;
      
   type Data_Array is array (Size_T range <>) of aliased Integer;

   package Data_Pointers is
      new Interfaces.C.Pointers
             (Index => Size_T,
              Element => Integer,
              Element_Array => Data_Array,
              Default_Terminator => 0);
                                              
end Index_Rejection;

However, when compiled using GNAT 3.13p on Windows 95, the compiler complains
with an error message of  'index_rejection.ads:14:32: index types of actual do
not match those of formal "Element_Array"'. On the other hand, if Size_T on
lines 8 and 12 is fully qualified as shown below, the compiler was happy. 

with Global;
with Interfaces.C.Pointers;

package Index_Rejection is

   use Global;
      
   type Data_Array is array (Global.Size_T range <>) of aliased Integer;

   package Data_Pointers is
      new Interfaces.C.Pointers
             (Index => Global.Size_T,
              Element => Integer,
              Element_Array => Data_Array,
              Default_Terminator => 0);
                                              
end Index_Rejection;

Am I correct to conclude that there is a bug in the compiler?

Anh Vo




^ permalink raw reply	[relevance 7%]

* Re: Questions: interfacing to C
  2001-01-02  4:54  4%   ` Robert Dewar
@ 2001-01-02  5:15  0%     ` Julian Morrison
  0 siblings, 0 replies; 144+ results
From: Julian Morrison @ 2001-01-02  5:15 UTC (permalink / raw)


"Robert Dewar" <robert_dewar@my-deja.com> wrote:

> I really don't see why Interfaces.C.Pointers is relevant here.
> Everything that is needed here can likely be found in Annex B.
> 
> Part of the trouble is that we do not have enough information in the
> question, what does "shim" mean? One does not interface directly to
> types, but typically through procedure calls, so what we really need
> here is the full set of declarations.

I'm trying to "pragma Import" some C functions (a subset of OpenSSL's
crypto stuff, to be exact) and I have to build Ada equivalents of the
structs it requires and sometimes returns, so I can pass them around and
poke about inside (eg: to set up a RSA key struct from a received binary
public-key). I'm trying to figure the limits of what the language will do
for me as a freebie - as versus what I have to manually convert.
 
> Note that convention C_Pass_By_Copy is also relevant in this
> discussion.,

Where in the ARM is that one defined? I can't find the dratted thing.

PS, to you and anyone else who's responded, thanks :-)



^ permalink raw reply	[relevance 0%]

* Re: Questions: interfacing to C
  2001-01-02  4:19  5% ` James Rogers
  2001-01-02  4:54  4%   ` Robert Dewar
@ 2001-01-02  4:56  0%   ` Julian Morrison
  1 sibling, 0 replies; 144+ results
From: Julian Morrison @ 2001-01-02  4:56 UTC (permalink / raw)


"James Rogers" <jimmaureenrogers@worldnet.att.net> wrote:

> Your two questions seem to be summarized by: "How do I bind to a C
> pointer?"
> 
> The answer is to use the package Interfaces.C.Pointers. This package is
> described in section B.3.2 of the Ada Reference Manual.

I know the "pragma Import" converts some of the stuff (record to struct*)
but not if it converts returned pointers.

I also don't know if "pragma Convention (C, FOO)" allows access elements
within FOO to map straight onto equivalent pointers in the C struct
version.



^ permalink raw reply	[relevance 0%]

* Re: Questions: interfacing to C
  2001-01-02  4:19  5% ` James Rogers
@ 2001-01-02  4:54  4%   ` Robert Dewar
  2001-01-02  5:15  0%     ` Julian Morrison
  2001-01-02  4:56  0%   ` Julian Morrison
  1 sibling, 1 reply; 144+ results
From: Robert Dewar @ 2001-01-02  4:54 UTC (permalink / raw)


In article <3A515730.D2106823@worldnet.att.net>,
  James Rogers <jimmaureenrogers@worldnet.att.net> wrote:
> Your two questions seem to be summarized by: "How do I bind
to a C
> pointer?"
>
> The answer is to use the package Interfaces.C.Pointers. This
> package is described in section B.3.2 of the Ada Reference
Manual.


I really don't see why Interfaces.C.Pointers is relevant here.
Everything that is needed here can likely be found in Annex B.

Part of the trouble is that we do not have enough information
in the question, what does "shim" mean? One does not interface
directly to types, but typically through procedure calls, so
what we really need here is the full set of declarations.

Note that convention C_Pass_By_Copy is also relevant in this
discussion.,


Sent via Deja.com
http://www.deja.com/



^ permalink raw reply	[relevance 4%]

* Re: Questions: interfacing to C
  @ 2001-01-02  4:19  5% ` James Rogers
  2001-01-02  4:54  4%   ` Robert Dewar
  2001-01-02  4:56  0%   ` Julian Morrison
  0 siblings, 2 replies; 144+ results
From: James Rogers @ 2001-01-02  4:19 UTC (permalink / raw)


Your two questions seem to be summarized by: "How do I bind to a C
pointer?"

The answer is to use the package Interfaces.C.Pointers. This
package is described in section B.3.2 of the Ada Reference Manual.

Jim Rogers
Colorado Springs, Colorado USA



^ permalink raw reply	[relevance 5%]

* Generic package question
@ 2000-12-16  8:41  5% Julian Morrison
  0 siblings, 0 replies; 144+ results
From: Julian Morrison @ 2000-12-16  8:41 UTC (permalink / raw)


I'm trying to instantiate Interfaces.C.Pointers as a child of my own Bytes
mini package, I'd like to end up with a case where I can just "use
Bytes.Pointers" from another package and get the instance. Is there any
way I can do this?



^ permalink raw reply	[relevance 5%]

* RE: Variable length raw-byte data
@ 2000-12-12  3:30  5% Beard, Frank
  0 siblings, 0 replies; 144+ results
From: Beard, Frank @ 2000-12-12  3:30 UTC (permalink / raw)
  To: 'comp.lang.ada@ada.eu.org'

Try looking at Interfaces.C and Interfaces.C.Pointers.
If it's string data, look at Interfaces.C.Strings.
I've used this successfully to interface to C.

Or

In your interface routine, receive the pointer as an
address, and then unchecked convert it.

  type Byte is mod 2**8;

  type Byte_Array is array (positive range <>) of Byte;

  type Byte_Array_Pointer is access Byte_Array;

  buffer_Address : System.Address;
  buffer_Pointer : Byte_Array_Pointer;

begin
...
  status := Get_C_Stuff(length         => length,
                        buffer_Address => buffer_Address);

  if (length > 0) then
    declare
      subtype Constrained_Byte_Array is Byte_Array(1..length);
      function To_Buffer_Pointer is
        new Ada.Unchecked_Conversion(System.Address,Constrained_Byte_Array);
    begin
      buffer_Pointer := To_Buffer_Pointer(buffer_Address);
    end;
    ...
  end if;
...

Something like that.  (Constructive corrections only please!)
I haven't done it this way in a while.

Frank

-----Original Message-----
From: Julian Morrison [mailto:julian.morrison@virgin.net]
Sent: Monday, December 11, 2000 2:38 PM
To: comp.lang.ada@ada.eu.org
Subject: Variable length raw-byte data


I'm trying to shim to a C library that returns some data as a length in
bytes and a pointer to the first byte. The length is not known at compile
time. Is there any way I can morph this into an array of mod 2**8? I'm
using the latest Linux GNAT.
_______________________________________________
comp.lang.ada mailing list
comp.lang.ada@ada.eu.org
http://ada.eu.org/mailman/listinfo/comp.lang.ada




^ permalink raw reply	[relevance 5%]

* Re: Calling C function in Ada
       [not found]     <8qgon0$469$1@nnrp1.deja.com>
@ 2000-10-09  0:00  5% ` John McCabe
  0 siblings, 0 replies; 144+ results
From: John McCabe @ 2000-10-09  0:00 UTC (permalink / raw)


ebresie@usa.net wrote:

> I am currently working on trying to have access to some of the protocol
>and service functions which are part of C and I think I am having some
>problems.  I am still very new to using C functions in Ada..so it may
>just be a usage issue.
>
>How is the best way to handle the passing in of the char * type variabls
>and the char ** type variables?

Use Interfaces.C.Strings.chars_ptr and its associated operations for
char * stuff. You mention To_Ada, but you need to use function Value
to return a string, and function New_String to return a chars_ptr from
a string.

As for char **, I used an instantiation of Interfaces.C.Pointers.

Hope this helps.


Best Regards
John McCabe <john@assen.demon.co.uk>




^ permalink raw reply	[relevance 5%]

* Re: Trouble with UNIX IPC and Ada95
  @ 2000-08-31 22:57  4%     ` John McCabe
  0 siblings, 0 replies; 144+ results
From: John McCabe @ 2000-08-31 22:57 UTC (permalink / raw)


Charles Hixson <charleshixsn@earthlink.net> wrote:

>"trust C"?  That's not exactly the question. 

>The main problem is pointers.

Refer to the package Interfaces.C.Pointers.


Best Regards
John McCabe <john@assen.demon.co.uk>



^ permalink raw reply	[relevance 4%]

* Re: Array access via pointer?
  @ 2000-08-04  0:00  3%           ` Robert I. Eachus
  0 siblings, 0 replies; 144+ results
From: Robert I. Eachus @ 2000-08-04  0:00 UTC (permalink / raw)


Ken Garlington wrote:
 
> No, you don't have to allocate the arrays in the heap -- so long as you're
> willing to accept the risks of converting a System.Address to an access
> type! (For the specific example I gave, the risks appear to be low in my
> experience.)

   And my experience has been quite the opposite!  If your only use of
the 'trick' is to convert the address of an object to an access value
designating the object, it will usually work.  In general in Ada 95 the
address of an array object should be the address of the first element:

   "For an array X, X'Address should point at the first component of the
array,
and not at the array bounds."  RM 13.3(14)

   The first thing to note about the paragraph quoted above is that this
is in a section titled, "Implementation Advice."  Of course, most
compilers do follow this advice.  However, if you pass in the address of
a component of the array, other than the first, things will often go
wrong.  Some compilers implement the above advice by storing any
necessary descriptor data at a negative offset from the address, which
is probably deadly in the case under discussion.  Other compilers do
this by materializing the descriptor data where necessary and, if
necessary  by passing additional 'hidden' parameters as part of calls
with parameters of the array base type, whether or not the parameter
subtype is actually constrained.  In this case, if you don't materialize
the data in an Ada array, the compiler has no place to go to find the
attributes it needs to create the call. Often this means that you need
an object, sometimes a constant object, which has the correct
attributes.  You then can use an attribute definition clause to say that
the object is located at the address of the actual data.  Remember that
in Ada you can have a nested declare block--or even a procedure or
function--that declares both the subtype bounds and the address
differently each time it is entered:

    procedure Map_Array(Addr: in System.Address; First, Last: in
Integer) is
      Temp: My_Array_Type(First..Last);
      for Temp'Address use Addr;
    begin
      Some_Stuff;
      -- in here it is safe to treat the data as an Ada array,
      -- assuming all the parameters are correct.
    end Map_Array;

    You can even make Map_Array a generic procedure with a subprogram
parameter,
and use it to apply different actions to the array.  Sound complex? 
Actually this approach to interfacing to hardware or other programming
languages can get much hairier.  If you are interfacing to actual
hardware registers or to code running in another thread, you may also
need to specify pragmas Atomic, Atomic_Components, Volatile or
Volatile_Components.  Figuring out which you may need is a non-trivial
exercise, and is common to all interfaces no matter how they are
declared.

   The right solution, at least to the interfacing problems is to use
Annex B.  After all that is what it is there for.  In this particular
example, the package Interfaces.C.Pointers may be just what the doctor
ordered.  Again, though, if you are interfacing to hardware or to
another thread or process, watch it.  It is up to you to warn the Ada
compiler what the other guy is doing using the above pragmas.




^ permalink raw reply	[relevance 3%]

* Re: New to ada95: porting
  @ 2000-02-29  0:00  7% ` James S. Rogers
  0 siblings, 0 replies; 144+ results
From: James S. Rogers @ 2000-02-29  0:00 UTC (permalink / raw)



Al Johnston wrote in message <38BAF3B2.69D7A905@mindspring.com>...
>things of particular interests are
>1) access types to 1-d unconstrained arrays
>2) access types to 1-d unconstrained array whose elements are also
>1-d unconstrained arrays.
>3) using 'address on an ada string type when interfacing to a c
>* char type
>4) generation of ada strings by c-code (via calls to ada library
>linked into a c program)


Look at the standard C interface utilities in the packages
Interfaces.C and Interfaces.C.Pointers.

Interfaces.C provides a lot of commonly needed conversions, including
to and from C strings.

Interfaces.C.Pointers is a generic package providing a wealth of C-style
operations on pointers.

When in doubt read the Reference Manual.

Jim Rogers
Colorado Springs, Colorado






^ permalink raw reply	[relevance 7%]

* Re: More C
       [not found]     <vhizotrc4x7.fsf@grotte.ifi.uio.no>
@ 2000-01-30  0:00  6% ` Nick Roberts
  0 siblings, 0 replies; 144+ results
From: Nick Roberts @ 2000-01-30  0:00 UTC (permalink / raw)


With the greatest respect, I think this a classic case of C programmer
trying to make Ada do things the way they have to be done in C.

In Ada, you are able to specify the representation of types, and you also
have recourse to the standard Interfaces.C package (and its children) for
interfacing to C functions and objects. This means that, in Ada, you can
often specify types that correspond more closely to the high-level meaning
of a type, and let representation clauses, as well as type derivation
techniques, take care of the nitty gritty details of how they should be
represented in the machine.

   type Light_Level_8 is range 0..255;
   for Light_Level_8'Size use 8;

   type SDL_Color is
      record
         Red, Green, Blue: Light_Level_8;
      end record;

   for SDL_Color use
      record
         Red at 0 range 0..7;
         Green at 0 range 8..15;
         Red at 0 range 16.23;
      end record;

   for SDL_Color'Size use 32;

   type SDL_Color_Array is array (Integer) of aliased SDL_Color;

   SDLCT: SDL_Color := (0,0,0); -- default 'terminator' of arrays
   -- provided because Interfaces.C.Pointers needs it, but unlikely to be
used

   package SDL_Color_Pointers is
      new Interfaces.C.Pointers(Integer,SDL_Color,SDL_Color_Array,SDLCT);

   subtype Color_Count is Interfaces.C.Int range 0..Interfaces.C.Int'Last;

   type SDL_Palette is
      record
         Number_Of_Colors: Color_Count;
         Colors: SDL_Color_Pointers.Pointer;
      end record;

   Int_Size: constant := Interfaces.C.Int'Size;

   for SDL_Palette use
      record
         Number_of_Colors at 0 range 0..Int_Size-1;
         Colors at 0 range
Int_Size..Int_Size+SDL_Color_Pointers.Pointer'Size-1;
      end record;

You can use the Value function (and others) of the SDL_Color_Pointers
package to access, easily and efficiently, the contents of arrays pointed to
by the Colors component.

Ada offers a particularly better way of accessing your display buffer.

   type Light_Level_2 is range 0..3;
   for Light_Level_2'Size use 2;

   type Light_Level_3 is range 0..7;
   for Light_Level_3'Size use 3;

   type Color_Descriptor_8 is
      record
         Red, Green: Light_Level_3;
         Blue: Light_Level_2;
      end record;

   for Color_Desriptor_8 use
      record
         Red: at 0 range 0..2;
         Green: at 0 range 3..5;
         Blue: at 0 range 6..7;
      end record;

   -- and so on for Color_Descriptor_16 and Color_Descriptor_32

   type Display_Buffer_8 is array (Integer, Integer) of aliased
Color_Descriptor_8;
   type Display_Buffer_16 is array (Integer, Integer) of aliased
Color_Descriptor_16;
   type Display_Buffer_32 is array (Integer, Integer) of aliased
Color_Descriptor_32;

   pragma Convention(Fortran,Display_Buffer_8);
   pragma Convention(Fortran,Display_Buffer_16);
   pragma Convention(Fortran,Display_Buffer_32);
   -- for (X,Y) ensure X dimension varies faster than Y

   package Display_Buffer_8_Pointers is
      new
Interfaces.C.Pointers(Integer,Color_Descriptor_8,Display_Buffer_8,...);
   -- etc

   subtype CGA_Buffer is Display_Buffer_8(1..320,1..200);
   for CGA_Buffer'Size use 320*200*8;
   pragma Volatile(CGA_Buffer); -- tell Ada it's memory mapped

   type CGA_Buffer_Access is access all CGA_Buffer;

You might import 'data', using the Import pragma, use Unchecked_Conversion
to typecast it as a Display_Buffer_8/16/32_Pointers.Pointer, and then
convert from Display_Buffer_8/16/32_Pointers.Pointer to CGA_Buffer_Access
(for example). Now you can read from and write into the buffer just like you
would a normal two-dimensional Ada array. You can't really get much more
convenient than that.

NB: the two-dimensional array addressing should be optimised adequately by
most Ada compilers, but if not, and you need the extra speed, you can use
the Value function (and others) to access the contents of the display
buffers instead. In cases such as this, try to 'wrap up' higher level
operations into procedures and functions; the Inline pragma can be used to
prevent this technique from reducing speed.

Best of luck!

--
Nick Roberts
http://www.adapower.com/lab/adaos







^ permalink raw reply	[relevance 6%]

* Re: Interfacing to C non-void procedure with "out" parameters
  @ 2000-01-14  0:00  6% ` Ted Dennison
  2000-01-14  0:00  0%   ` Jeff Carter
  0 siblings, 1 reply; 144+ results
From: Ted Dennison @ 2000-01-14  0:00 UTC (permalink / raw)


In article <387f1c30.12554815@news.rdg.ac.uk>,
  S.J.Sangwine@Reading.ac.uk (Dr Steve Sangwine) wrote:
> Can anyone shed light on the issue of interfacing between Ada95 and C
> where there is a C procedure (non-void) which returns a result *and*
> modifies some of its parameters?

Sure; It can't happen. C routines can't modify their parameters. They
are all "in".

They can of course pass in *pointers* to objects and merrily modify the
pointed-to objects. You can do that with Ada functions too.

> I have a C procedure, for which I wanted to write an Ada95 spec, and
> import the C object code using pragma Import. Since the C procedure
> has a return result, I need an Ada function (or do I?). An Ada

Yup. Unless you are using Gnat. In that cause you could use pramga
Import_Valued_Procedure (I think I got the name right, but check).
However, that will render your binding unusable to other compilers.

> function must have parameters of mode 'in', implicitly or explicity,
> yet the C procedure will modify one or more of its parameters. To be
> safe, I wrote a wrapper procedure in C which had an extra parameter,
> and called this from Ada. The wrapper procedure called the real C
> procedure and returned the return result of the real C procedure in
> the extra parameter. That way the Ada spec can be a procedure and
> everything is watertight, but it is a nuisance to have this extra,
> trivial C wrapper procedure in between.

What I typically do is interface straight to the C routine in Ada, using
access or System.Address types where appropriate. Then I write a wrapper
routine in *Ada*, that provides a nice non-pointer Ada-like interface
(with status checks converted to exceptions, etc).

For instance, suppose we have the following (made up) C routine:

   int esGetValue (int key, const int *value);

The idea being that you pass in a key and get back a value for it. The
function returns 1 on success, 0 on failure.

On the Ada side, we'd much prefer to access this routine thusly:

   Get_Failed : exception; -- raised by Get_Value when the get fails

   function Get_Value (Key : Integer) return Integer;


First you interface to the routine to create your thin binding:

   function esGetValue (Key   : in Interfaces.C.Int;
                        Value : in System.Address
                       ) return Interfaces.C.Int;
   pragma Import (C, esGetValue, "esGetValue");

Note that for the "int *" parameter I used System.Address. This is not
officially portable, but in practice works on every normal platform. You
could instead use a type instantiated from Interfaces.C.Pointers for int
to achieve theoretical portability.

Finally we create our thick binding with the desired interface.

   function Get_Value (Key : Integer) return Integer is
      Value : aliased Interfaces.C.Int;
      use type Interfaces.C.Int; -- Give access to "=" operator
   begin
      if
        esGetValue
          (Key   => Interfaces.C.Int(Key),
           Value => Value
          ) = 0
      then
         raise Get_Failed;
      end if;
      return Integer(Value);
   end Get_Value;

--
T.E.D.

http://www.telepath.com/~dennison/Ted/TED.html


Sent via Deja.com http://www.deja.com/
Before you buy.




^ permalink raw reply	[relevance 6%]

* Re: Interfacing to C non-void procedure with "out" parameters
  2000-01-14  0:00  6% ` Ted Dennison
@ 2000-01-14  0:00  0%   ` Jeff Carter
  0 siblings, 0 replies; 144+ results
From: Jeff Carter @ 2000-01-14  0:00 UTC (permalink / raw)


In article <85ngl3$10s$1@nnrp1.deja.com>,
  Ted Dennison <dennison@telepath.com> wrote:
> In article <387f1c30.12554815@news.rdg.ac.uk>,
> For instance, suppose we have the following (made up) C routine:
>
>    int esGetValue (int key, const int *value);
>
> The idea being that you pass in a key and get back a value for it. The
> function returns 1 on success, 0 on failure.
>
> On the Ada side, we'd much prefer to access this routine thusly:
>
>    Get_Failed : exception; -- raised by Get_Value when the get fails
>
>    function Get_Value (Key : Integer) return Integer;
>
> First you interface to the routine to create your thin binding:
>
>    function esGetValue (Key   : in Interfaces.C.Int;
>                         Value : in System.Address
>                        ) return Interfaces.C.Int;
>    pragma Import (C, esGetValue, "esGetValue");
>
> Note that for the "int *" parameter I used System.Address. This is not
> officially portable, but in practice works on every normal platform.
You
> could instead use a type instantiated from Interfaces.C.Pointers for
int
> to achieve theoretical portability.

There's no reason to use System.Address here. Use an access parameter:

function Es_Get_Value
   (Key : Interfaces.C.Int; Value : access Interfaces.C.Int)
return Interfaces.C.Int;
pragma Import (C, ...);

>
> Finally we create our thick binding with the desired interface.
>
>    function Get_Value (Key : Integer) return Integer is
>       Value : aliased Interfaces.C.Int;
>       use type Interfaces.C.Int; -- Give access to "=" operator
>    begin
>       if
>         esGetValue
>           (Key   => Interfaces.C.Int(Key),
>            Value => Value
>           ) = 0
>       then
>          raise Get_Failed;
>       end if;
>       return Integer(Value);
>    end Get_Value;

Note that the call here should not compile; Value is not of type
System.Address. With an access parameter, use Value => Value'access and
everything should be fine.
--
Jeff Carter
"Now go away or I shall taunt you a second time."
-- Monty Python and the Holy Grail


Sent via Deja.com http://www.deja.com/
Before you buy.




^ permalink raw reply	[relevance 0%]

* Re: Get a pointer to an array
  @ 1999-06-06  0:00  6% ` David Botton
  0 siblings, 0 replies; 144+ results
From: David Botton @ 1999-06-06  0:00 UTC (permalink / raw)


You take the access/address of the first element.
a(1)'address or a(1)'access in your code.

And to get back from an address/access to an array you should use the
Interfaces.C.Pointers generic package. (see
http://www.adapower.com/os/com-bstr.html for an example of using
Interfaces.C.Pointers)

Also not if you are trying to work with C:

RM B.3:70

An Ada parameter of an array type with component type T, of any mode, is
passed as a t* argument to a C function, where t is the C type
corresponding to the Ada type T.


David Botton


Elad Rosenheim wrote:
> 
> This question may seem easy, but I haven't been able to find
> a solution:
> 
> How do I create a normal array, then point an access type to it?
> I tried to convert the array 'address attribute to the array access
> type,
> but it didn't work. I think ADA arrays have some "meta data" before
> the data that contains the array bounds, and the 'address attribute
> gives the address of the data storage itself. So how can I make the
> access
> variable point to the array?
> 
> This doesn't work:
> 
>     type int_array is array(integer <>) of integer;
>     type int_access is access int_array;
> 
>     function To_Int_Access is new Unchecked_Conversion(
>         system.address, int_access);
> ...
> 
> declare
>     a : int_array(1..10);
>     b : int_access;
> begin
>     a :=  To_Int_Access(a'address);
> ...
> 
> Please help me with this one.
> 
> Thanks,
> Elad Rosenheim.




^ permalink raw reply	[relevance 6%]

* how to read C extern variables from Ada?
  @ 1999-02-28  0:00  7% ` David C. Hoos, Sr.
  0 siblings, 0 replies; 144+ results
From: David C. Hoos, Sr. @ 1999-02-28  0:00 UTC (permalink / raw)



how to read C extern variables from Ada? wrote in message
<7bbd3c$gf7@drn.newsguy.com>...
>Hello,
>
>It is easy to interface to C from Ada. But one problem that I could not
>see mentioned in annex B, is how to get access to 'extern' variables.
>
>For example, I can call getopt() from Ada. But the problem is that getopt()
>sets values into an extern variables that are defined is C header files,
>and so can be read from C client programs after the call to getopt()
>returns.
>
>--------------------
>SYNOPSIS
>    #include <unistd.h>
>
>    int getopt(int argc, char * const argv[], const char *optstring);
>    extern char *optarg;
>    extern int optind, opterr, optopt;
>-----------------------
>
>So, in the above, after I call getopt(), I need a way to 'read' optarg.
There
>is no C API to read optarg. So, How to do this in Ada??
>
The simple answer is that one uses pragma import, e.g.:

Option_Argument : Interfaces.C.Char_Array;
pragma Import (C. Option_Argument, "optarg");

But, the details get a little messy.  Here's a possible implementation:

--- begin source code ---
with Ada.Command_Line;
with Ada.Text_Io;
with Interfaces.C.Pointers;
with System;
procedure Command_Line_Options is
   package C_String_Pointers is new Interfaces.C.Pointers
     (Index => Interfaces.C.Size_T,
      Element => Interfaces.C.Char,
      Element_Array => Interfaces.C.Char_Array,
      Default_Terminator => Interfaces.C.Nul);

   type C_String_Vector is array (Interfaces.C.Size_T range <>) of
     aliased C_String_Pointers.Pointer;

   package C_String_Vector_Pointers is new Interfaces.C.Pointers
     (Index => Interfaces.C.Size_T,
      Element => C_String_Pointers.Pointer,
      Element_Array => C_String_Vector,
      Default_Terminator => Null);

   subtype String_Pointer is C_String_Pointers.Pointer;

   subtype C_String_Vector_Pointer is C_String_Vector_Pointers.Pointer;

   use type Interfaces.C.Char_Array;
   use type Interfaces.C.Int;
   use type C_String_Pointers.Pointer;

   function Next_Option_Character_Pos
     (Argument_Count  : in Interfaces.C.Int;
      Argument_Vector_Pointer : in C_String_Vector_Pointer;
      Option_String   : in Interfaces.C.Char_Array)
      return Interfaces.C.Int;
   pragma Import (C, Next_Option_Character_Pos, "getopt");

   Argument_Vector_Pointer : C_String_Vector_Pointer;
   pragma Import (C, Argument_Vector_Pointer, "gnat_argv");

   Argument_Vector : constant C_String_Vector :=
     C_String_Vector_Pointers.Value (Ref => Argument_Vector_Pointer);

   Argument_Count : constant Interfaces.C.Int := Argument_Vector'Length - 1;
   Option_Argument_Pointer : C_String_Pointers.Pointer;
   pragma Import (C, Option_Argument_Pointer, "optarg");

   Option_Character_Pos : Interfaces.C.Int := 0;
   Option_Character : Character;

   Option_Index  :  Interfaces.C.Int;
   pragma Import (C, Option_Index, "optind");

   Option_Error  :  Interfaces.C.Int;
   pragma Import (C, Option_Error, "opterr");

   Option_Option :  Interfaces.C.Int;
   pragma Import (C, Option_Option, "optopt");

begin

   Ada.Text_Io.Put_Line
     ("Argument count =>" & Interfaces.C.Int'Image (Argument_Count));

   for A in Argument_Vector'First ..
     Interfaces.C.Size_T'Pred (Argument_Vector'Last) loop
      Ada.Text_Io.Put_Line
        ("Argument (" & Interfaces.C.Size_T'Image (A) & ") is """ &
         Interfaces.C.To_Ada
         (C_String_Pointers.Value (Argument_Vector (A))) &
         """");
   end loop;

     Option_Error := 1;

     loop
        Option_Character_Pos := Next_Option_Character_Pos
          (Argument_Count =>  Argument_Count,
           Argument_Vector_Pointer => Argument_Vector_Pointer,
           Option_String => "a:bc" & Interfaces.C.nul);

        exit when Option_Character_Pos < 0 or else Option_Character_Pos >
255;

        Option_Character := Character'Val (Option_Character_Pos);

        Ada.Text_Io.Put_Line
          ("Option_Index =" &
           Interfaces.C.Int'Image (Option_Index));

        Ada.Text_Io.Put_Line
          ("Option_Option =" &
           Interfaces.C.Int'Image (Option_Option));

        Ada.Text_Io.Put_Line
          ("Option_Character =" & Option_Character);

        for A in Argument_Vector'First ..
          Interfaces.C.Size_T'Pred (Argument_Vector'Last) loop
           Ada.Text_Io.Put_Line
             ("Argument (" & Interfaces.C.Size_T'Image (A) & ") is """ &
              Interfaces.C.To_Ada
              (C_String_Pointers.Value (Argument_Vector (A))) &
              """");
        end loop;

          if Option_Argument_Pointer /= null then
             Ada.Text_Io.Put_Line
               ("Option argument = """ &
                Interfaces.C.To_Ada
                (C_String_Pointers.Value (Option_Argument_Pointer)));
          end if;

     end loop;

end Command_Line_Options;

--- end source code ---








^ permalink raw reply	[relevance 7%]

* Re: Alternate to Unchecked_Conversion - Portable?
  1999-02-23  0:00  5%     ` Christopher Green
@ 1999-02-25  0:00  0%       ` robert_dewar
  1999-02-24  0:00  5%         ` Christopher Green
  0 siblings, 1 reply; 144+ results
From: robert_dewar @ 1999-02-25  0:00 UTC (permalink / raw)


In article <36d3ba85.713118@nntp.concentric.net>,
  cjrgreen@concentric.net (Christopher Green) wrote:
> In
> this case, it is natural enough, though not fully
> portable, to declare an Ada array of the actual
> size and map it onto the C array with an address
> clause.

In Ada 83, this is ALWAYS an incorrect approach, because
it is erroneous, which means the compiler need make no
attempt at all (e.g. in suppressing optimziation) to
make this "work".

> In Ada 95, the package Interfaces.C.Pointers is
> a better solution to this kind of problem.

If you look at the implementation of this package, it
will almost certainly use unchecked conversion on pointers!

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[relevance 0%]

* Re: Alternate to Unchecked_Conversion - Portable?
  1999-02-25  0:00  0%       ` robert_dewar
@ 1999-02-24  0:00  5%         ` Christopher Green
  0 siblings, 0 replies; 144+ results
From: Christopher Green @ 1999-02-24  0:00 UTC (permalink / raw)


On Thu, 25 Feb 1999 04:57:04 GMT, robert_dewar@my-dejanews.com wrote:

>In article <36d3ba85.713118@nntp.concentric.net>,
>  cjrgreen@concentric.net (Christopher Green) wrote:
>> In
>> this case, it is natural enough, though not fully
>> portable, to declare an Ada array of the actual
>> size and map it onto the C array with an address
>> clause.
>
>In Ada 83, this is ALWAYS an incorrect approach, because
>it is erroneous, which means the compiler need make no
>attempt at all (e.g. in suppressing optimziation) to
>make this "work".

Such compilers (there are a few still in use) are, for reasons
like this, virtually useless for the sort of programming in which
address clauses, Unchecked_Conversion, or equivalence
between C pointer types and Ada access types is important.

Theoretical correctness and actual correct operation are
different things.  There are many compilers on which the
address clause mapping does work as it "should".

>> In Ada 95, the package Interfaces.C.Pointers is
>> a better solution to this kind of problem.
>
>If you look at the implementation of this package, it
>will almost certainly use unchecked conversion on pointers!

True; however, the level of abstraction in using
Interfaces.C.Pointers is higher, and the reduction
in programming effort and improvement in port-
ability may be worth any trade in efficiency.

Furthermore, if the Unchecked_Conversions
internal to the Interfaces.C.Pointers package
don't do the right thing, you can at least blame
the compiler vendor.  If you code Unchecked_
Conversions on your own and they don't do the
right thing on the platforms you must support,
you're stuck.

>-----------== Posted via Deja News, The Discussion Network ==----------
>http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    

-- 
Chris Green
Advanced Technology Center
Laguna Hills, California





^ permalink raw reply	[relevance 5%]

* Re: Alternate to Unchecked_Conversion - Portable?
  @ 1999-02-23  0:00  5%     ` Christopher Green
  1999-02-25  0:00  0%       ` robert_dewar
  0 siblings, 1 reply; 144+ results
From: Christopher Green @ 1999-02-23  0:00 UTC (permalink / raw)


On Wed, 24 Feb 1999 02:52:52 GMT, robert_dewar@my-dejanews.com wrote:

>In article <36d2638e.6427631@nntp.concentric.net>,
>  cjrgreen@concentric.net (Christopher Green) wrote:
>> It is primarily useful in situations in which alternative
>> implementations end up causing a bitwise copy.  If
>> the object to be converted is large, or the conversion
>> must be done many times, this can be a win.
>
>This seems bogus to me. If you replace this by unchecked
>conversion of *pointers* (i.e. access values), NOT the
>items themselves, then there is no bit copying, and no
>inefficiency at all in the access.
>
>-----------== Posted via Deja News, The Discussion Network ==----------
>http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    

The situations I'm thinking of involve conversion of
arrays of integers or pointers, large record objects,
and the like. You are surely right in that there is no
inherent reason why Unchecked_Conversion on
scalars and pointers should be inefficient.

For example, in X Window System programming, 
there are many C functions that return arrays of
indefinite size (the size must be obtained through
another argument or another function call).  In
this case, it is natural enough, though not fully
portable, to declare an Ada array of the actual
size and map it onto the C array with an address
clause.

In Ada 95, the package Interfaces.C.Pointers is
a better solution to this kind of problem.

-- 
Chris Green
Advanced Technology Center
Laguna Hills, California




^ permalink raw reply	[relevance 5%]

* Re: Alternate to Unchecked_Conversion - Portable?
  @ 1999-02-22  0:00  4% ` Christopher Green
    0 siblings, 1 reply; 144+ results
From: Christopher Green @ 1999-02-22  0:00 UTC (permalink / raw)


On Sun, 21 Feb 1999 11:33:54 -0800, "Steve Doiel"
<nospam_steved@pacifier.com> wrote:

>I discovered a technique for performing a similar function to
>Unchecked_Conversion.  Locating two data structures at the same address by
>defining the first normally and then using an address clause to locate the
>second at the same address as the first (as shown in the following sample):
>
>
>WITH Ada.Text_Io;
>WITH Interfaces;
> USE Interfaces;
>PROCEDURE TestAlias IS
>  PACKAGE Text_Io RENAMES Ada.Text_Io;
>
>  TYPE aRec IS
>    RECORD
>      f1 : Integer_32;
>      f2 : Integer_32;
>    END RECORD;
>
>  TYPE Integer_16_Array IS ARRAY( Positive RANGE <> ) OF Integer_16;
>
>  v1 : aRec;
>  v2 : Integer_16_Array( 1..4 );
>  FOR v2'ADDRESS USE v1'ADDRESS;    -- This causes v1 and v2 to occupy the
>same memory
>
>BEGIN
>  v1.f1 := 1;
>  v1.f2 := 2;
>  FOR ii IN v2'RANGE LOOP
>    Text_Io.Put( Integer_16'IMAGE( v2( ii ) ) );
>  END LOOP;
>  Text_Io.New_Line;
>END TestAlias;
>
>
>My question is: is this portable?
>
>I expect that record layouts will be dependent on different endian machines,
>and I know that this technique is inherently unsafe, but it makes things
>very simple.
>
>SteveD
>
>

It is primarily useful in situations in which alternative
implementations end up causing a bitwise copy.  If
the object to be converted is large, or the conversion
must be done many times, this can be a win.

Other than problems with data representation mis-
matches, a source of significant portability problems
is default initializations. For example, certain compilers
will apply default initializations to arrays of derived types
of System.Address, zeroing out the contents of the
array you were trying to convert.

Unless there are overriding reasons to do otherwise;
for example, a need to preserve backward com-
patibility with Ada 83, or a big performance difference
in a particular implementation, it is safer and usually
more efficient to use packages intended for this
purpose, such as Interfaces.C.Pointers.




^ permalink raw reply	[relevance 4%]

* Re: win32ada design question/problem
  1998-11-17  0:00  4%         ` dennison
  1998-11-17  0:00  4%           ` Tucker Taft
@ 1998-11-17  0:00  5%           ` Mats Weber
  1 sibling, 0 replies; 144+ results
From: Mats Weber @ 1998-11-17  0:00 UTC (permalink / raw)


dennison@telepath.com wrote:

> The "portable" alternative we are given is Interfaces.C.Pointers. But its a
> real pain to use for routines where the input object could be any type.

Interfaces.C.Pointers also has the nasty problem that you must use
'Unchecked_Access instead of 'Access all the time, unless you
instantiate it in the same scope as your objects.

Also, as you are interfacing Zlib, you will be dealing with untyped
pointers all the time, so I think System.Address is really the way to go.




^ permalink raw reply	[relevance 5%]

* Re: win32ada design question/problem
  @ 1998-11-17  0:00  4%         ` dennison
  1998-11-17  0:00  4%           ` Tucker Taft
  1998-11-17  0:00  5%           ` Mats Weber
  0 siblings, 2 replies; 144+ results
From: dennison @ 1998-11-17  0:00 UTC (permalink / raw)


In article <36519A6A.C07508F5@elca-matrix.ch>,
  Mats.Weber@elca-matrix.ch wrote:
> dennison@telepath.com wrote:
> >
> > In article <ubtm7cxj0.fsf@gsfc.nasa.gov>,
> >   Stephen Leake <Stephen.Leake@gsfc.nasa.gov> wrote:
> > >
> > > While I agree it wasn't well designed, I don't agree you need to go to
> > > a thick binding. The binding should use 'out' parameter modes in the
> > > places where C uses pointers to achieve output parameters. Most
> > > compilers will map an 'out' parameter to a C pointer, since that's
> > > what 'by reference' means.
> >
> > Actually, according to B.3(68), that is *required* behavour. The problem
with
> > that technique is that many C routines attach a signifigance to a incomming
> > value of null. You won't be able to produce such a value on the Ada side, so
> > some of the functionality of the C routine will be lost.
>
> And there is another, more severe problem. The C function may allocate
> some memory that you must free later, e.g.
>
> procedure P (X : out Some_Record_Type);
> pragma Import(C, P);
>
> now as you have no pointer to the returned data, you cannot free it.
>
> I think the Ada 83 classic int + System.Address approach is better in
> this case.
>

I'm trying to write some portable bindings to the Zlib compression library
right now, and have found myself reverting to just that. But are there
portability issues associated with System.Address? My reading of 13.7 is that
System.Address does not nessecarily map to a C pointer, and that
System.Null_Address does not nessecarily map to a C null pointer.

The "portable" alternative we are given is Interfaces.C.Pointers. But its a
real pain to use for routines where the input object could be any type.

--
T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[relevance 4%]

* Re: win32ada design question/problem
  1998-11-17  0:00  4%         ` dennison
@ 1998-11-17  0:00  4%           ` Tucker Taft
  1998-11-17  0:00  5%           ` Mats Weber
  1 sibling, 0 replies; 144+ results
From: Tucker Taft @ 1998-11-17  0:00 UTC (permalink / raw)


dennison@telepath.com wrote:

: ...
: I'm trying to write some portable bindings to the Zlib compression library
: right now, and have found myself reverting to just that. But are there
: portability issues associated with System.Address? My reading of 13.7 is that
: System.Address does not nessecarily map to a C pointer, and that
: System.Null_Address does not nessecarily map to a C null pointer.

: The "portable" alternative we are given is Interfaces.C.Pointers. But its a
: real pain to use for routines where the input object could be any type.

I would not worry about the portability of System.Address.
Theoretically it might be a problem, but practically,
I doubt very much whether you will run into any problems
on hosts and targets you care about.

System.Null_Address is perhaps slightly more likely to cause
portability problems, though still I suspect you are in the
0.01% case.  You could always define your own "C_Null" in some
common target-specific package, with the 99.99% reusable
default definition of System.Null_Address.

: --
: T.E.D.

--
-Tucker Taft   stt@inmet.com   http://www.inmet.com/~stt/
Intermetrics, Inc.  Burlington, MA  USA
An AverStar Company




^ permalink raw reply	[relevance 4%]

* Re: null pointer representation (was: Boolean Representation)
  @ 1998-09-27  0:00  4%       ` Keith Thompson
  0 siblings, 0 replies; 144+ results
From: Keith Thompson @ 1998-09-27  0:00 UTC (permalink / raw)


evans@evans.pgh.pa.us (Arthur Evans Jr) writes:
> In article <yec1zoyd2xa.fsf@king.cts.com>,
> Keith Thompson <kst@king.cts.com> wrote:
> 
> > Nor can we assume that a ... null pointer is represented as all-bits-zero
> 
> Indeed not.  Some years ago I was concerned about this very issue and
> asked around (probably on cla) about it.  The answers were instructive.
> Most compilers did in fact use all zeros, but some other values were
> used, including one compiler (from IBM, I think) that used the HEX
> number DEAD BEEF.  I suppose it really stood out in HEX dumps.
> 
> Since I was interfacing to C-code in Ada-83 and code on the C side
> needed zero for null pointers, I ended up writing some extra code to
> ensure that value, even though the implementation I was then using
> represented the null pointer as zero.

Incidentally (and only slightly off-topic), C also does not guarantee
that a null pointer is represented as all-bits-zero.  There's enough C
code out there that assumes that it is that almost all C compilers use
the "expected" representation, but there's no such requirement.  (The
issue is further confused by the fact that the source representation
of a C null pointer is an integer literal 0.)  See the comp.lang.c FAQ
for an extensive discussion of this.

Getting back to Ada, I was a little surprised to see that the generic
package Interfaces.C.Pointers doesn't explicitly declare a constant
corresponding to a C NULL pointer, but this should be covered by the
statement that the type Pointer is C-compatible.  So Ada 95
programmers shouldn't have to worry about it as long as they use the
interfacing features provided by the language.

-- 
Keith Thompson (The_Other_Keith) kst@cts.com <http://www.ghoti.net/~kst> <*>
Qualcomm, San Diego, California, USA  <http://www.qualcomm.com>
It takes a Viking to raze a village.




^ permalink raw reply	[relevance 4%]

* Re: type names (was Re: Child package: private type and IO)
  1998-03-01  0:00  2%       ` Matthew Heaney
@ 1998-03-04  0:00  2%         ` Fergus Henderson
  0 siblings, 0 replies; 144+ results
From: Fergus Henderson @ 1998-03-04  0:00 UTC (permalink / raw)



mheaney@ni.net (Matthew Heaney) writes:

 >blaak@infomatch.com (Ray Blaak) wrote:
 >
 >>>Objects are the memory locations that store a value of a type.
 >>
 >>But you are using the word here as a type! (i.e. the set of things that are
 >>memory locations that store values).
 >
 >No.  You are confused about what a type is.

No, Ray Blaak is correct here.

 >Let's begin by defining what we mean by a type.  A type is defined as "A
 >set of values, and a set of operations on those values."  For example,  I
 >can define a type
 >
 >with the name "Integer"
 >
 >and the set of values
 >
 >   ..., -3, -2, -1, 0, 1, 2, 3, ...
 >
 >and the set of operations
 >
 >   +: Integer x Integer -> Integer
 >   -: Integer x Integer -> Integer
 >   *: Integer x Integer -> Integer
 >   /: Integer x Integer -> Integer
 >   =: Integer x Integer -> Boolean
 >
 >etc

Agreed.

Above, you used the word "Object" to refer to a type with the name "Object",
with the set of values being the different possible memory locations,
and with the set of operations being fetch, store, etc.

Below, you assume that "Object" and "Type" are mutually exclusive;
this is true in Ada, but there are other languages for which it is not true.

 >A type refers to the set of values, NOT the objects.  An object is a memory
 >location inside a computer, that stores a value, a value we interpret as
 >having a certain type.  So when we declare an object,
 >
 >O : T;
 >
 >we're allocating a memory cell, and we're interpreting the value of the
 >data in that cell as being of type T.  The means the memory cell designated
 >by object O will only contain certain values, and that only certain
 >operations may be applied to the value in that cell.
 >
 >The memory cell designated by object O isn't really interesting.  It's the
 >data in that cell that's interesting.  And it's the data in the cell that
 >"is of type T," not the object itself.

No, the object itself "is [an lvalue] of type T".

To say otherwise would imply that objects are untyped, that
only values are typed, and that it is therefore possible to
store a value of any type in a given object.  This is true
for some untyped languages, but it is not true in Ada.

 >It is completely wrong to name a type "Object."

Well, I don't particularly like this convention much myself;
but I think "completely wrong" is overstating the case.

 >Yes, it's true we often say "Object O has type T," but we really mean "O is
 >the name of a memory cell containing a value of type T."

No.  What we really mean is "O has type n<T>",
where "n<T>" is a (parametric) type whose operations
include "fetch" (syntactically implicit in Ada) and "store" (`:=').

"n<T>" might be better named "name<T>", "lvalue<T>", or even "object<T>".

 >>>A type should be named using a noun phrase, such as
 >>>type Singly_Linked_List is ...;
 >>
 >>I think that style of type names used really depends on if type names are
 >>qualified with package names or not.
 >
 >Of course, a type name should NOT be qualified by a package name.  A type
 >name is a type name, and a package name is a package name.  A package name
 >is NOT a type name, and in no way participates in naming a type.  

No, a package name surely does participate in naming a type,
for the type's fully-qualified name includes the name of the
package in which it is contained.

 >A package is a namespace, and serves only to prevent clashes among
 >similarly named types in an otherwise global namespace.

No, packages also provide encapsulation, not just namespace control.

 >A package disambiguates type names, but it is itself not a type name.

Agreed.

 >To use a package as part of the type, as in 
 >
 >package P is 
 >
 >   type Object is ...;
 >...
 >end P;
 >
 >The_Object : P.Object;
 >
 >so that the "real" type name is "P.Object" only confuses the difference
 >between a module and a type.

Nonsense!

The package name is P; the type name is P.Object
(though it can be abbreviated as Object, in certain contexts).
What's there to be confused about?

 >>Having:
 >>
 >>  package Linked_List is
 >>    type Linked_List is ...
 >>  end Linked_List;
 >>
 >>results in usage like:
 >>
 >>  Employees : Linked_List.Linked_List;
 >>
 >>which I personally find irritating.
 >
 >The package is misnamed.  A common idiom, and a very OLD idiom in the Ada
 >community, is to use the plural of the type name as the package name,

Well, that doesn't help much -- now the usage is

    Employees : Linked_Lists.Linked_List;

which is still just as ugly.

 >I'm sorry you find this convention irritating.  If so, then you can tell
 >the language designers that they named the packages
 >
 >Ada.Characters
 >Ada.Interrupts
 >Ada.Interrupts.Names
 >Ada.Exceptions
 >Ada.Numerics
 >Ada.Streams
 >Ada.Strings
 >Interfaces
 >Interfaces.C.Pointers
 >Interfaces.C.Strings
 >System.Address_To_Access_Conversions
 >System.Storage_Elements
 >System.Storage_Pools
 >
 >incorrectly, and that the names they chose irritate you.

It's not a question of "correct" or "incorrect", it's a question
of style.  The style chosen for the standard library strongly
encourages the use of `use', to avoid unnecessary redundancy in
names like `Ada.Strings.Unbounded.Unbounded_String'.
This is probably not such a bad thing
for the standard library, since experienced Ada programmers 
will know the standard library well; but for more general settings,
encouraging the use of `use' may not be such a good idea.

Personally, I quite like the style of naming types `T',
e.g. `Ada.Strings.Unbounded.T'.

 >> However a package like:
 >>
 >>  package Linked_List is
 >>    type Object is ...
 >>  end Linked_List;
 >>
 >>results in usage like:
 >>
 >>  Employees : Linked_List.Object;
 >>
 >>which reads better to me.
 >
 >It reads better to you because you are confused.  You don't understand the
 >difference between a module and a type.

Well, it reads better to me too, and I definitely do
understand the difference between a module and a type
(and I think Ray Blaak probably does too).

 >If you don't believe that this is the Ada idiom, [...]

I think Ada is big enough for more than one idiom!

--
Fergus Henderson              | Designing grand concepts is fun;
fjh@cs.mu.oz.au               | finding nitty little bugs is just work.
http://www.cs.mu.oz.au/~fjh   | -- Brooks, in "The Mythical Man-Month".
PGP key fingerprint: 00 D7 A2 27 65 09 B6 AC  8B 3E 0F 01 E7 5D C4 3F




^ permalink raw reply	[relevance 2%]

* Re: type names (was Re: Child package: private type and IO)
  @ 1998-03-01  0:00  2%       ` Matthew Heaney
  1998-03-04  0:00  2%         ` Fergus Henderson
  0 siblings, 1 reply; 144+ results
From: Matthew Heaney @ 1998-03-01  0:00 UTC (permalink / raw)



In article <6dcio1$fvo$1@berlin.infomatch.com>, blaak@infomatch.com (Ray
Blaak) wrote:

>>Objects are the memory locations that store a value of a type.
>
>But you are using the word here as a type! (i.e. the set of things that are
>memory locations that store values).

No.  You are confused about what a type is.

Let's begin by defining what we mean by a type.  A type is defined as "A
set of values, and a set of operations on those values."  For example,  I
can define a type

with the name "Integer"

and the set of values

   ..., -3, -2, -1, 0, 1, 2, 3, ...

and the set of operations

   +: Integer x Integer -> Integer
   -: Integer x Integer -> Integer
   *: Integer x Integer -> Integer
   /: Integer x Integer -> Integer
   =: Integer x Integer -> Boolean

etc

A type refers to the set of values, NOT the objects.  An object is a memory
location inside a computer, that stores a value, a value we interpret as
having a certain type.  So when we declare an object,

O : T;

we're allocating a memory cell, and we're interpreting the value of the
data in that cell as being of type T.  The means the memory cell designated
by object O will only contain certain values, and that only certain
operations may be applied to the value in that cell.

The memory cell designated by object O isn't really interesting.  It's the
data in that cell that's interesting.  And it's the data in the cell that
"is of type T," not the object itself.
   
It is completely wrong to name a type "Object."  There are 2 reasons:

1) It confuses the difference between a memory cell (which merely stores a
value) and the value itself.  "Type" refers to a set of values, and to the
operations you can perform to manipulate those values.

"Type" does NOT refer to the memory cell containing a value.  The term we
use to refer to a memory cell containing a value is "Object."

Yes, it's true we often say "Object O has type T," but we really mean "O is
the name of a memory cell containing a value of type T."

The name "T" is the name we've bound to the TYPE, not to the object.  So
"T" is the name by which we refer to a set of values and a set of
operations.  The name "O" is the name we bind to an OBJECT, not a type;
that is, "O" refers to a memory cell.

So when you name a type "Object," it's confusing because the term "Object"
refers to a memory cell.  But a type is NOT a memory call, it's a set of
values.

2) It confuses the difference between a module and a type.

In Ada, module and type are ORTHOGONAL language features.  This really
confuses a lot of people, and I have no idea why.

The Ada language construct for a module is a package.  A package is NOT a
type.  A package which exports a type declaration merely demarcates the
"primitive" operations of a type among all the operations that have the
type as a parameter or return value.  

The Ada language construct for a type comprises 2 parts:

a) a type declaration, which binds a name to the type, specifies its class,
and specifies the set of values as a range (or implied range).

b) subprogram declarations, which take parameters of the type, or return
values of the type.

Consider this example:

package P is

   type T is range 1 .. 4;

   procedure Op1 (O : T);

   function Op2 (F : Float) return T;

end P;

with P;
package Q is

   procedure Op3 (O : P.T);

end Q;

Let's analyze this piece by piece.

The declaration 

   type T is range 1 .. 4;

a) specifies the type class, here Integer

b) specifies the set of values (having the Integer class) for the type,
here 1, 2, 3, 4

c) binds a name to the type, here "T"

d) specifies primitive operations that are "predefined" for this class of
type, here

   +: T x T -> T
   +: T -> T
   -: T x T -> T
   -: T -> T
   =: T x T -> Boolean

etc

The operations Op1 and Op2 are also "primitive" operations of the type
whose name is T.  We say they are "user-defined," in contrast to the
"predefined" primitive operations as addition, subtraction, etc.

They are primitive because they take a parameter of the type (Op1) and
return a value of the type (Op2), and they are declared in the same package
(P) as the type declaration.

By contrast, the operation Op3 is NOT a "primitive" operation of the type
whose name is T.  Even though Op3 takes a parameter of type P.T, it is not
primitive because it is not declared in the same package as the type
declaration.

We make the distinction between primitive and non-primitive operations
because only the former are "inherited" during a derivation.  For example,

with P;
package R is

   type NT is new P.T;

  procedure Op4 (O : NT);

end R;

The primitive operations of type R.NT are "+", "-", "*", "/", etc, and Op1,
Op2, and Op4.  Op1 and Op2 (and addition, etc) are inherited from T, and a
new primitive operation, Op4, was added too.

Note the Op3 is NOT an operation of type NT, because Op3 is not a primitive
operation of type T.

And by the way, while I'm on the subject, a "class" in other languages as
C++, Eiffel, and Java maps to an Ada tagged type.  It does NOT map to an
Ada package.  To convert the C++ declaration

class Stack ...;

to Ada, you have to do this:

package Stacks is

   type Stack is ...;  -- this is the "class Stack"


>>So when refer to an object's type as "Object," then how do you refer to the
>>object?
>
>Perhaps as An_Object, or The_List, or The_Set, or even Value. An even better
>approach is to use names from the domain, like maybe Employees, or
>Active_Flights, or Current_Account.

An an even better approach is

Account : Bank_Account;

File : Text_File;

Mode : File_Mode;


>>A type should be named using a noun phrase, such as
>>type Singly_Linked_List is ...;
>
>I think that style of type names used really depends on if type names are
>qualified with package names or not.

Of course, a type name should NOT be qualified by a package name.  A type
name is a type name, and a package name is a package name.  A package name
is NOT a type name, and in no way participates in naming a type.  

A package is a namespace, and serves only to prevent clashes among
similarly named types in an otherwise global namespace.  A package
disambiguates type names, but it is itself not a type name.

To use a package as part of the type, as in 

package P is 

   type Object is ...;
...
end P;

The_Object : P.Object;

so that the "real" type name is "P.Object" only confuses the difference
between a module and a type.

>Having:
>
>  package Linked_List is
>    type Linked_List is ...
>  end Linked_List;
>
>results in usage like:
>
>  Employees : Linked_List.Linked_List;
>
>which I personally find irritating.

The package is misnamed.  A common idiom, and a very OLD idiom in the Ada
community, is to use the plural of the type name as the package name, as in


generic
...
package Stacks

   type Stack is ...;
...;
end Stacks;

I'm sorry you find this convention irritating.  If so, then you can tell
the language designers that they named the packages

Ada.Characters
Ada.Interrupts
Ada.Interrupts.Names
Ada.Exceptions
Ada.Numerics
Ada.Streams
Ada.Strings
Interfaces
Interfaces.C.Pointers
Interfaces.C.Strings
System.Address_To_Access_Conversions
System.Storage_Elements
System.Storage_Pools

incorrectly, and that the names they chose irritate you.

> However a package like:
>
>  package Linked_List is
>    type Object is ...
>  end Linked_List;
>
>results in usage like:
>
>  Employees : Linked_List.Object;
>
>which reads better to me.

It reads better to you because you are confused.  You don't understand the
difference between a module and a type.

>Note this does not imply that all types should be
>called "Object" either. With this example in particular, it is natural to work
>with objects and references to objects:
>
>  type Handle;
>  type Object is record
>    ...
>        Next : Handle;
>        Previous : Handle;
>  end record;
>  type Handle is access Object;


This is another horrible naming convention.  The term "handle" loosely
refers to a pointer-to-pointer.  Handles are used in memory allocation
schemes to allow you to relocate chunks of memory to reduce fragmentation
(Mac programmers will know what I'm talking about).

The Ada idiom for a name of an access type is T_Access, for example

type Stack is tagged private;

type Stack_Access is access all Stack;

type Stack_Class_Access is access all Stack'Class;

Do not name an access type Handle, because it is not a handle.

Do not name an access type Pointer, because access objects are not
pointers.  If they were, then Jean Ichbiah would have chosen the keyword
"pointer" instead of "access," right?

If you don't believe that this is the Ada idiom, then make note of the
names of the types

Ada.Text_IO.File_Access

Ada.Strings.Unbounded.String_Access

Ada.Streams.Stream_IO.Stream_Access


>then one can say things like:
>
>  Manager_Subset : Linked_List.Handle;
>
>which is really clear (to me, of course :-).
>
>If one uses use clauses a lot, then of course more descriptive type names are
>better:
>
>  data : Linked_List;

Ahh, that's more like it.

Here's an example from a library I'm writing:

package ACL.Lists is ...;


package ACL.Lists.Single is

   type Single_List is private;
...;
end ACL.Lists.Single;


package ACL.Lists.Double is

   type Double_List is private;
...
end ACL.Lists.Double;


Here's another example you often find in tutorials:

package Bank_Accounts is

   type Bank_Account is abstract tagged limited private;
...;
end Bank_Accounts;


package Bank_Accounts.Checking is

   type Checking_Account is new Bank_Account with private;
...;
end Bank_Accounts.Checking;


package Bank_Accounts.Savings is

   type Savings_Account is new Bank_Account with private;
...
end Bank_Accounts.Savings;


>>A good guideline is, Be consistant with the style in the reference manual. 
>>There are NO types in the RM named "Object," so there should be none in
>>your code either.
>
>One shouldn't be so afraid to do something different, if one thinks it is an
>improvement. How else can standards get better?

A bunch of guys from all over the planet with PhDs in computer science
designed the language, and somehow they didn't come up with your "better
idea."  Telling, isn't it?  If you think it is an improvement, perhaps that
is because there is knowledge that you don't have.




^ permalink raw reply	[relevance 2%]

* Re: MD5 Function in Ada
@ 1997-06-06  0:00  5% Jerry van Dijk
  0 siblings, 0 replies; 144+ results
From: Jerry van Dijk @ 1997-06-06  0:00 UTC (permalink / raw)



Jon, long time since C_ECHO :-)

In article <Pine.LNX.3.91.970604091908.3334A-100000@weck.bro jguthrie@brokersys.com writes:

>That's okay.  I actually expected someone to suggest linking in a C source
>file.  As a matter of fact, I have two different MD5 implementations in C
>source (and I could type in the one in APPLIED CRYPTOGRAPHY if I wanted a
>third.) I just don't want to have to figure out how to call C code from
>Ada in order to implement this.

Actually, using GNAT, this doesn't take much figuring out:

   /* interface to 'int do_something(int input) */
   function Do_Something (Input : in Integer) return Integer;
   pragma Import (C, Do_Something, "do_something);

as in GNAT there's a direct correspondence between the Ada and C type's.

If you do not want to rely on this, standard Ada95 with support for
Annex B (Interface to other languages), has the package Interfaces.C
defining them portably (and also have Interfaces.C.Strings and
Interfaces.C.Pointers).

--

-- Jerry van Dijk       | Leiden, Holland
-- Consultant           | Team Ada
-- Ordina Finance       | jdijk@acm.org




^ permalink raw reply	[relevance 5%]

* Re: Using Motif/AXI XmStringTable in ADA
  @ 1997-02-22  0:00  6% ` Nigel J. Tracey
  0 siblings, 0 replies; 144+ results
From: Nigel J. Tracey @ 1997-02-22  0:00 UTC (permalink / raw)
  To: James Rice


In article <1997Feb20.201801.29759@relay.nswc.navy.mil>,
	jamrice7@themall.net (James Rice) writes:
>Sorry if this is a stupid question, or not phrased well, I am not very 
>experienced with ADA or the AXI bindings.  I do know Motif though.
>
>I am having a problem converting a Motif type to ADA, I am utilizing AXI Motif 
>bindings.  I want to get all selected items from a Listbox widget.  Motif in C 
>would return a StringTable, which is a pointer to some number of XmStrings, 
>which I can traverse like an array, accessing the indivual strings.  With the 
>bindings, I am returned a pointer, but how do I use it?  The relationship 
>between pointers and arrays, is definitely not the same in ADA as it is in C.  
>My question is, how do I get to the individual XmStrings in ADA.  Once I get a 
>XmString, the AXI version of StringGetLtoR( ) will convert the XmString to an 
>ADA String, so that is no problem.  
>
>Thanks in advance for any help,
>Jim.

You can use the generic Interfaces.C.Pointers package to convert
the pointer to an array. The function Interfaces.C.Pointers.Value
will return an array which has one element for each of the XmStrings.

I have done this for XmNchildren resources something like below

with Interfaces.C.Pointers

..

   type Widget_Array_Type is array (Integer range <>) of
      aliased Xt.Intrinsic.Widget;

    function To_Widget is new Ada.Unchecked_Conversion
       (Integer_Access, Xt.Intrinsic.Widget);

   package Widget_List_Package is new Interfaces.C.Pointers
      (Integer, Xt.Intrinsic.Widget, Widget_Array_Type, To_Widget (null));

   Num_Children          : aliased Integer;
   Children              : aliased Xt.Intrinsic.WidgetList;

begin

      Xt.Intrinsic.XtVaGetValues
        (GUI_Widgets.Test,
         Stdarg.Empty &
           XmNnumChildren & To_Integer (Num_Children'Unchecked_Access) &
           XmNchildren & To_Integer (Children'Unchecked_Access) &
         null);

      declare
         Widget_List : Widget_Array_Type (1 .. Num_Children);
         Pointer     : Widget_List_Package.Pointer :=
           Widget_List_Package.Pointer (Children);
         Set_State   : aliased Boolean;
      begin
         Widget_List := Widget_List_Package.Value
                          (Pointer,
                           Interfaces.C.Ptrdiff_t (Num_Children));
         for I in Widget_List'range loop
            Xt.Intrinsic.XtVaGetValues
              (Widget_List (I),
               Stdarg.Empty &
                 XmNset & To_Integer (Set_State'Unchecked_Access) &
               null);
            if Set_State then
               Selected_Test_Type := Execute_Modules.Test_Type'Val (I - 1);
               exit;
            end if;
         end loop;
      end;
..

Hope that helps some,

Nigel

--------------------
Nigel J. Tracey MEng, Research Associate (High Integrity Systems Group).
Department of Computer Science,   Office: X/D016
University of York,               Tel   : [0|+44]1904 432769
York, England.                    E-Mail: njt@minster.york.ac.uk
YO1 5DD.                          URL   : http://sv1pc161.cs.york.ac.uk/~njt





^ permalink raw reply	[relevance 6%]

* Interfacing to C, output arrays
@ 1996-12-02  0:00  5% Simon Wright
  0 siblings, 0 replies; 144+ results
From: Simon Wright @ 1996-12-02  0:00 UTC (permalink / raw)



The code below shows an interface to a C function
  int accessor(int n, int* a);
which fills the n-element array a with data.

The code works just fine with Gnat 3.07 (OSF, Linux) but I think I may
be just 'lucky'.

The purpose of the subtype This_Arr is to make sure that the parameter
passed to the C code doesn't have any 'extraneous' constraint info at
the front (in fact, Gnat seems to pass the address of the first
element even to the Ada procedure anyway). Gnat warns that Result is
never assigned a value (that is, the Result out parameter to the Ada
procedure), so I'm concerned that another compiler might handle things
differently.

The Rationale doesn't cover the case of array parameters
(Interfaces.C.Pointers doesn't seem relevant here), but LRM B.3(70)
seems to indicate that I'm OK. Any thoughts?

--
with Interfaces.C;
package Inter is
  type Arr is array (Integer range <>) of Interfaces.C.Int;
  procedure Accessor (Result : out Arr);
end Inter;

package body Inter is
  procedure Accessor (Result : out Arr) is
    subtype This_Arr is Arr (Result'Range);
    function Accessor (N : Interfaces.C.Int;
		       Result : This_Arr) return Interfaces.C.Int;
    pragma Import (C, Accessor, "accessor");
    Count : Interfaces.C.Int;
  begin
    Count := Accessor (N => Result'Length, Result => Result);
  end Accessor;
end Inter;




^ permalink raw reply	[relevance 5%]

* How to supply pointer to C?
@ 1996-08-27  0:00  6% Greg Baker
  1996-08-27  0:00  0% ` David C. Hoos, Sr.
  0 siblings, 1 reply; 144+ results
From: Greg Baker @ 1996-08-27  0:00 UTC (permalink / raw)



Interfaces.C.Pointers.Value can get you from a C array to an Ada
array,  and Interfaces.C.To_C can get you from a String to a
null-terminated block of chars,  but what if I want to get a block of
ints,  for examples?

More generally, what if I have some object and I want to pass its
address to some C function.  (The question arises as I am trying to
write an Ada gdbm interface - gdbm_store takes as arguments structs of
the form-
  struct { char * dptr;   int data_size; }.
(i.e. record 
         dptr : Interfaces.C.Pointers.???
         data_size : Interfaces.C.int
      end;
)

I'm kind of hoping to do something like

  x.dptr := Magical_Conversion_function ( object'Access ); 
  x.data_size = object'Size;

Any suggestions?

-- 
Gregory D. Baker        gbaker@rp.csiro.au         CSIRO Radiophysics 
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  
   - predictions of the future - quantum computers - silly poetry  -
   - the "langue musicale universale" (Solresol)  revival project  - 
   - - - - - - - - http://www.rp.csiro.au/~gbaker  - - - - - - - - -
I'm an eccentric mathematician/IT guru/communicator,  and I'm looking
               for a new job in Sydney,  Australia.




^ permalink raw reply	[relevance 6%]

* Re: Ada/C [GNAT]: Accessing C arrays from Ada
  @ 1996-08-27  0:00  3% ` David C. Hoos, Sr.
  0 siblings, 0 replies; 144+ results
From: David C. Hoos, Sr. @ 1996-08-27  0:00 UTC (permalink / raw)



Hi Michael,
Michael K Rohan <mrohan@ix.netcom.com> wrote in article
<32225A96.4512F115@ix.netcom.com>...
> Hello,
> 
> I'm trying to figure out the best way to use a C pointer as an array
> from Ada.  I have a C service function which returns the number of items
> and a pointer to a vector of the items:
> 
>         Query(int *n, item** items);
> 
> Interfacing from Ada is OK: I can get the number of items and the
> pointer as an "access all Item", but how do I access the individual
> items?
> 
> Thank you, in advance, for any help/info,
> Michael.
> 
Assuming that the C function Query allocates memory for the items, you need
to do something like the following:

Here is a library-level Ada procedure which demonstrates what you want to
do.   It has been tested with gnat 3.05 on IRIX 5.3]
VADS 623.53.3 on IRIX 5.3 and IRIX 6.2, and with gnat 3.04a on Win95.

Note that there are many other ways this could have been done.  For
example, if we were not looking for Ada 83 compatibility, we could use the
Interfaces.C.Pointers package from Ada 95's Annex B.

This approach shows how to declare an array which takes on the attributes
'FIRST, 'LAST 'LENGTH, etc., corresponding to the number of elements
returned by the C function.  This allows passing the Ada array to another
Ada subprogram, for example.

with System;
with Text_IO;
procedure Do_Something is
  subtype ITEM_TYPE is INTEGER;  -- Ada Equivalent of the C item type
  -- We use INTEGER here only for example.
  
  -- The type of an array of items
  type ITEM_ARRAY_TYPE is array (POSITIVE range <>) of ITEM_TYPE;
  
  -- The Ada specification of the C function   
  procedure Query (
      Number_Of_Items_Address    : in System.ADDRESS;
      Item_Array_Address_Address : in System.ADDRESS
      );
  
  -- The ada "implementation" of the C function is to interface to the C
  -- function's implementation.
  pragma INTERFACE (C, Query);
  
  The_Item_Array_Address : System.ADDRESS;
  -- This is where we will tell the Query function to put the address of
the
  -- array of items it has allocated.
  
  The_Number_Of_Items    : NATURAL;
  -- This is where we will tell the Query function to put the number of
items
  -- in the array.
begin
  -- Call the query function.
  Query (
    Number_Of_Items_Address    => The_Number_Of_Items'ADDRESS,
    Item_Array_Address_Address => The_Item_Array_Address'ADDRESS
    );
    
  -- Now that we know how many items are in the array we can declare the
array
  -- object.
  declare
    -- This is required for Ada 95.  See further note below.
    The_Constant_Item_Array_Address : constant System.ADDRESS := 
        The_Item_Array_Address;
	
    -- This is the array declaration.
    The_Item_Array : ITEM_ARRAY_TYPE (1 .. The_Number_Of_Items);
    
    -- This is the address clause which defines the location of the array
of
    -- items.  NOTE:  In Ada95, Address clauses must have constant
addresses,
    -- hence the need to declare the constant above.  In Ada83 we could
have
    -- just used the variable set by Query, directly.
    for The_Item_Array use at The_Constant_Item_Array_Address;
    
  begin
    -- Here we demonstrate that we have the correct data
    for i in The_Item_Array'RANGE loop
      Text_IO.Put_Line (
          "Item (" & INTEGER'IMAGE (i) & " ) =>" &
          INTEGER'IMAGE (The_Item_Array (i))
          );
    end loop;
  end;
end Do_Something;
-- Example C source file for test 
-- #define length(a) (sizeof (a) / sizeof (* a)) 
-- static int data [] = {1,2,4,8,16,32,64,128};
-- /* NOTE: In a real implementation, the data is probably in dynamic
memory,
--    so, one would probably want an interface to "free", so that the
memory
--    could be deallocated from Ada code. */
-- void query (int * n, int ** items)
-- {
--   * n = length (data);
--   * items = data;
-- }
-- 

David C. Hoos, Sr.,
http://www.dbhwww.com
http://www.ada95.com






^ permalink raw reply	[relevance 3%]

* Re: How to supply pointer to C?
  1996-08-27  0:00  6% How to supply pointer to C? Greg Baker
@ 1996-08-27  0:00  0% ` David C. Hoos, Sr.
  0 siblings, 0 replies; 144+ results
From: David C. Hoos, Sr. @ 1996-08-27  0:00 UTC (permalink / raw)



Hi Greg,
This solution is a portable (i.e. Ada83/Ada95) solution, based on the
assumption that Ada's System.ADDRESS and C's pointer are the same size, and
have identical representations, and that Ada's INTEGER type and C's size_t
type are the same size, and have identical representations.  These
assumptions are usually true.
with System;
--The Ada record could be:
type WHATEVER is 
  record
    Data_Address : System.ADDRESS;
    Data_Size     : NATURAL;
end record;
-- A representation clause insures that the Ada compiler's representation
of the record
-- is the same as the C compiler's representation of the record.
-- Now, some may find fault with this "belt plus suspenders" approach, but
I've been burned
-- by so many compiler differences (even by variations between releases of
the
-- same compiler), that I feel this care is warranted.
for WHATEVER use
  record at mod 4;
    -- NOTE:  We make the assumption here that INTEGERs and ADDRESSes are
the same
    -- size, because in Ada 95, System.ADDRESS'SIZE is not a statuic
expression,
    -- hence can't be used in the record representation clause.
    Data_Address at 0 range 0 .. INTEGER'SIZE -1;
    Data_Size    at 0 range INTEGER'SIZE .. 2 * INTEGER'SIZE - 1;
  end record;

--Now, then if the data items are of some type, say, ITEM_TYPE, then
objects can be
--declared as
An_Item : ITEM_TYPE;
--and a record object can be declared as
A_Whatever : WHATEVER :=
--and the record can be initialized with the following aggregate expression
    (Data_Address => An_Item'ADDRESS, Data_Size => An_Item'SIZE /
System.STORAGE_UNIT);

Hope this helps.

David C. Hoos, Sr.,
http://www.dbhwww.com
http://www.ada95.com

Greg Baker <gbaker@walleroo.rp.csiro.au> wrote in article
<85ybj1zcdu.fsf@walleroo.rp.CSIRO.AU>...
> Interfaces.C.Pointers.Value can get you from a C array to an Ada
> array,  and Interfaces.C.To_C can get you from a String to a
> null-terminated block of chars,  but what if I want to get a block of
> ints,  for examples?
> 
> More generally, what if I have some object and I want to pass its
> address to some C function.  (The question arises as I am trying to
> write an Ada gdbm interface - gdbm_store takes as arguments structs of
> the form-
>   struct { char * dptr;   int data_size; }.
> (i.e. record 
>          dptr : Interfaces.C.Pointers.???
>          data_size : Interfaces.C.int
>       end;
> )
> 
> I'm kind of hoping to do something like
> 
>   x.dptr := Magical_Conversion_function ( object'Access ); 
>   x.data_size = object'Size;
> 
> Any suggestions?
> 
> -- 
> Gregory D. Baker        gbaker@rp.csiro.au         CSIRO Radiophysics 
>    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  
>    - predictions of the future - quantum computers - silly poetry  -
>    - the "langue musicale universale" (Solresol)  revival project  - 
>    - - - - - - - - http://www.rp.csiro.au/~gbaker  - - - - - - - - -
> I'm an eccentric mathematician/IT guru/communicator,  and I'm looking
>                for a new job in Sydney,  Australia.
> 




^ permalink raw reply	[relevance 0%]

* Re: Help needed to write bindings
  1995-04-03  0:00  5%   ` Samuel Tardieu
@ 1995-04-04  0:00  6%     ` David Arno
  0 siblings, 0 replies; 144+ results
From: David Arno @ 1995-04-04  0:00 UTC (permalink / raw)


In article <tardieuznfrzsckfmga@valjean.enst.fr>
           sam@inf.enst.fr "Samuel Tardieu" writes:

: These packages
: 
:   Interfaces.C
:   Interfaces.C.Strings
:   Interfaces.C.Pointers
: 
: are described in the RM (I think this is annex M). So bindings should
: tend to be compiler independent :)
: 
:   Sam

O.K., so I assumed Roger was refering to Ada 83, not Ada 95, perhaps
incorrectly.
-- 
David Arno




^ permalink raw reply	[relevance 6%]

* Re: Help needed to write bindings
  @ 1995-04-03  0:00  5%   ` Samuel Tardieu
  1995-04-04  0:00  6%     ` David Arno
  0 siblings, 1 reply; 144+ results
From: Samuel Tardieu @ 1995-04-03  0:00 UTC (permalink / raw)
  To: David Arno

>>>>> "David" == David Arno <davea@linkmsd.com> writes:

 David> In article <D66BIs.BGC@xvt.com> jimh@xvt.com "Roger Sheldon"
 David> writes: : Has there been any documentation of how to write Ada
 David> bindings?  : : I'm working on a project to write Ada bindings
 David> to a library : of C structures and functions.  :

 David> Unfortunately Roger, bindings tend to be compiler dependent,
 David> so your best bet is to read the compiler manuals.

These packages

  Interfaces.C
  Interfaces.C.Strings
  Interfaces.C.Pointers

are described in the RM (I think this is annex M). So bindings should
tend to be compiler independent :)

  Sam
--
"La cervelle des petits enfants, ca doit avoir comme un petit gout de noisette"
                                                       Charles Baudelaire




^ permalink raw reply	[relevance 5%]

* Re: Flags in Ada?
  @ 1994-10-26 15:54  3%   ` Andre Spiegel
  0 siblings, 0 replies; 144+ results
From: Andre Spiegel @ 1994-10-26 15:54 UTC (permalink / raw)


[referring to Norman H. Cohen's article <38jb6s$tsr@watnews1.watson.ibm.com>]

Thanks for the flag example. I had missed the section in the RM which
says that boolean operators can also be applied to boolean arrays. 
I suppose that compilers also recognize that what I want is bit
arithmetic, and therefore won't generate loops to apply the operator
to the arrays elementwise, which would of course be ridiculously slow.

Thanks also for the explanations on address clauses. This is the way
in which I have been doing it in my program, too. I was just wondering
about efficiency, because those `declare' statements "look" somewhat
expensive. For example, if UNIX fills a buffer with data items of
varying length (talking about ethernet packets, actually), and I want
to scan that buffer in an Ada loop, there has to be a declare
statement *within* the loop, in order to, sort of, "move" the record
pattern over the buffer.  

This seems a little counter-intuitive, because it's so different from
what you would do in C, for example -- simply declare a pointer to a
struct, and increment that pointer accordingly. I have found,
meanwhile, that in Ada 9X the generic package Interfaces.C.Pointers
will provide precisely that. But from what you wrote, I conclude that
the declare statement solution does not translate into anything
different at the machine level. It probably even looks more Ada-like.

--
Andre Spiegel                     |  This life is a test. It is only a test.
                                  |  Had this been an actual life, you would
University of Stuttgart, Germany  |  have received further instructions as to
Computer Science                  |  where to go and what to do.
                                                            -- Author unknown

	   email: spiegel@bruessel.informatik.uni-stuttgart.de



^ permalink raw reply	[relevance 3%]

Results 1-144 of 144 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
1994-10-25 10:36     Flags in Ada? Andre Spiegel
1994-10-25 16:19     ` Norman H. Cohen
1994-10-26 15:54  3%   ` Andre Spiegel
1995-03-28  0:00     Help needed to write bindings Roger Sheldon
1995-04-03  0:00     ` David Arno
1995-04-03  0:00  5%   ` Samuel Tardieu
1995-04-04  0:00  6%     ` David Arno
1996-08-26  0:00     Ada/C [GNAT]: Accessing C arrays from Ada Michael K Rohan
1996-08-27  0:00  3% ` David C. Hoos, Sr.
1996-08-27  0:00  6% How to supply pointer to C? Greg Baker
1996-08-27  0:00  0% ` David C. Hoos, Sr.
1996-12-02  0:00  5% Interfacing to C, output arrays Simon Wright
1997-02-20  0:00     Using Motif/AXI XmStringTable in ADA James Rice
1997-02-22  0:00  6% ` Nigel J. Tracey
1997-06-06  0:00  5% MD5 Function in Ada Jerry van Dijk
1998-02-14  0:00     Child package: private type and IO johnjohn
1998-02-17  0:00     ` sparre
1998-02-27  0:00       ` Matthew Heaney
1998-03-01  0:00         ` type names (was Re: Child package: private type and IO) Ray Blaak
1998-03-01  0:00  2%       ` Matthew Heaney
1998-03-04  0:00  2%         ` Fergus Henderson
1998-09-25  0:00     Boolean Representation Keith Thompson
1998-09-26  0:00     ` Tucker Taft
1998-09-26  0:00       ` Keith Thompson
1998-09-27  0:00         ` null pointer representation (was: Boolean Representation) Arthur Evans Jr
1998-09-27  0:00  4%       ` Keith Thompson
1998-11-13  0:00     win32ada design question/problem Mats Weber
1998-11-13  0:00     ` dennison
1998-11-16  0:00       ` Stephen Leake
1998-11-17  0:00         ` dennison
1998-11-17  0:00           ` Mats Weber
1998-11-17  0:00  4%         ` dennison
1998-11-17  0:00  4%           ` Tucker Taft
1998-11-17  0:00  5%           ` Mats Weber
1999-02-21  0:00     Alternate to Unchecked_Conversion - Portable? Steve Doiel
1999-02-22  0:00  4% ` Christopher Green
1999-02-24  0:00       ` robert_dewar
1999-02-23  0:00  5%     ` Christopher Green
1999-02-25  0:00  0%       ` robert_dewar
1999-02-24  0:00  5%         ` Christopher Green
1999-02-28  0:00     nabbasi@pacbell.net how to read C extern variables from Ada?
1999-02-28  0:00  7% ` how to read C extern variables from Ada? David C. Hoos, Sr.
1999-06-05  0:00     Get a pointer to an array Elad Rosenheim
1999-06-06  0:00  6% ` David Botton
2000-01-14  0:00     Interfacing to C non-void procedure with "out" parameters Dr Steve Sangwine
2000-01-14  0:00  6% ` Ted Dennison
2000-01-14  0:00  0%   ` Jeff Carter
     [not found]     <vhizotrc4x7.fsf@grotte.ifi.uio.no>
2000-01-30  0:00  6% ` More C Nick Roberts
2000-02-28  0:00     New to ada95: porting Al Johnston
2000-02-29  0:00  7% ` James S. Rogers
2000-08-01  0:00     Array access via pointer? Michael Carman
2000-08-01  0:00     ` Ted Dennison
2000-08-02  0:00       ` Michael Carman
2000-08-03  0:00         ` Ken Garlington
2000-08-03  0:00           ` Robert A Duff
2000-08-03  0:00             ` Ken Garlington
2000-08-04  0:00  3%           ` Robert I. Eachus
2000-08-30 16:16     Trouble with UNIX IPC and Ada95 berserker
2000-08-31 14:36     ` wv12
2000-08-31 15:27       ` Charles Hixson
2000-08-31 22:57  4%     ` John McCabe
     [not found]     <8qgon0$469$1@nnrp1.deja.com>
2000-10-09  0:00  5% ` Calling C function in Ada John McCabe
2000-12-12  3:30  5% Variable length raw-byte data Beard, Frank
2000-12-16  8:41  5% Generic package question Julian Morrison
2001-01-02  3:34     Questions: interfacing to C Julian Morrison
2001-01-02  4:19  5% ` James Rogers
2001-01-02  4:54  4%   ` Robert Dewar
2001-01-02  5:15  0%     ` Julian Morrison
2001-01-02  4:56  0%   ` Julian Morrison
2001-09-23 18:01  7% Possible Bug, Need Second Opinion ANH_VO
2001-10-29 20:19     Ada Address = C pointer ? Matthew Heaney
2001-10-30  9:58  5% ` M. A. Alves
2001-10-30 12:02  7%   ` Lutz Donnerhacke
2001-10-30 12:53  0%     ` M. A. Alves
2001-10-30 17:10  0%   ` Mark Johnson
2001-10-30 18:01  4%     ` M. A. Alves
2001-10-30 10:30     M. A. Alves
2001-10-30 19:53  0% ` tmoran
2001-10-31 13:01  0%   ` M. A. Alves
2001-10-30 14:19     Matthew Heaney
2001-10-30 14:41  5% ` M. A. Alves
2001-12-13  3:23     List Container Strawman 1.4 Ted Dennison
2001-12-24 13:57     ` Florian Weimer
2001-12-28 14:00       ` Ted Dennison
2001-12-28 16:43         ` Hyman Rosen
2001-12-28 19:49  3%       ` Matthew Heaney
2001-12-29 23:23  0%         ` Matthew Heaney
2002-04-25 11:44  3% Interfacing Ada95 to C++ - Object passing problem Markus Knauss
2002-04-25 17:43     C++ binding Dominique Devriese
2002-04-25 18:32  6% ` Pascal Obry
2002-04-30 13:27     ANN: GMGPL Claw Page Ted Dennison
2002-04-30 18:20  5% ` tmoran
2002-05-01 16:56  5%   ` Ted Dennison
2002-05-01 18:50  0%     ` Randy Brukardt
2002-05-30  6:34     C lib returns char** - How in ADA? Jeremy Cowgar
2002-05-30  7:56  6% ` sk
2002-06-12 16:09     newbie inquiry Steven Shaw
2002-06-12 16:26     ` Jean-Marc Bourguet
2002-06-12 18:09  6%   ` Pascal Obry
2002-07-22 15:26  5% Providing C function With Argv Jeff
2002-07-23  8:14  0% ` Ken Thomas
2002-07-24  6:18  0%   ` Jeff
2002-08-05 18:07     New to ada, a few questions Stephane Jolicoeur
2002-08-05 23:56     ` Keith Thompson
2002-08-06  2:31  5%   ` David C. Hoos, Sr.
2003-04-14 21:39     Interfacing Ada with C Paul Anderson
2003-04-16  2:56  7% ` Steve
2003-04-16  4:25  6%   ` Steve
2003-06-22  3:28 14% Interfaces.C.Pointers tmoran
2003-09-19 19:20     generic imports? void* -> generics? chris
2003-09-19 21:18  5% ` Nick Roberts
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-08  0:02  5%   ` sk
     [not found]       ` <3F83540E.5000302@myob.com>
2003-10-08  9:18  0%     ` Duncan Sands
2003-10-07 21:24     ` Duncan Sands
2003-10-08  2:14       ` Robert I. Eachus
2003-10-08  9:27         ` Duncan Sands
2003-10-08 22:43  3%       ` Robert I. Eachus
2003-10-09  9:31  0%         ` Duncan Sands
2004-05-11 13:14 12% C bindings, Interfaces.C.Pointers etc Dr. Adrian Wrigley
2004-05-11 18:17  8% ` tmoran
2004-05-11 18:48  7% ` Jeffrey Carter
2004-05-12  4:50  7%   ` Simon Wright
2004-05-13 15:26  8%   ` Dr. Adrian Wrigley
2004-05-12  6:30  7% ` Martin Krischik
2004-05-13 15:56  5%   ` Dr. Adrian Wrigley
2004-05-13 17:37 13%     ` Martin Krischik
2004-05-13 22:42  8%     ` Jeffrey Carter
2004-05-25 21:00     Question on interface Ada to C James Alan Farrell
2004-05-26  7:34  5% ` Martin Krischik
2004-08-18 22:27     Ada access vs C/C++ pointers and references Keith H Duggar
2004-08-19  0:21  6% ` Nick Roberts
2004-08-20  8:22     Ada equivalent to &#1057;++ header sentence Johnswort
2004-08-20 12:37  4% ` Stephen Leake
2004-08-24  3:32  5%   ` Randy Brukardt
2005-03-05 13:42     Teaching new tricks to an old dog (C++ -->Ada) Turamnvia Suouriviaskimatta
2005-03-06  1:01     ` [OT] " Martin Dowie
2005-03-08 12:14       ` Hans Malherbe
2005-03-08 15:31         ` Peter Amey
2005-03-08 18:33           ` CTips
2005-03-08 19:31             ` Dmitry A. Kazakov
2005-03-08 20:13               ` CTips
2005-03-08 20:38                 ` Martin Dowie
2005-03-09  2:43                   ` CTips
2005-03-09  4:34                     ` Jim Rogers
2005-03-09  5:46                       ` CTips
2005-03-09 19:27                         ` jimmaureenrogers
2005-03-10  2:09                           ` CTips
2005-03-10  2:35                             ` jimmaureenrogers
2005-03-11  4:58                               ` 10 rules for benchmarking (was Re: Teaching new tricks to an old dog (C++ -->Ada)) CTips
2005-03-11 12:18                                 ` Jean-Pierre Rosen
2005-03-11 14:00                                   ` CTips
2005-03-11 18:53                                     ` Pascal Obry
2005-03-11 19:24                                       ` CTips
2005-03-12  8:37                                         ` Georg Bauhaus
2005-03-12 17:29                                           ` CTips
2005-03-13  3:17                                             ` Jim Rogers
2005-03-13  4:10                                               ` CTips
2005-03-13 10:31  5%                                             ` Georg Bauhaus
2005-03-06  0:54     Memory limits in Ada where Fortran has none braver
2005-03-06  1:09     ` Jeff C
2005-03-06  6:18       ` braver
2005-03-06  9:26         ` Martin Krischik
2005-03-06 16:14           ` braver
2005-03-06 23:09  4%         ` Craig Carey
2005-04-09 19:30     Translate from C Jean-Baptiste CAMPESATO
2005-04-11 13:39  4% ` Steve
2005-05-03 23:49  5% Returning data from Ada to C igor.kh
2005-05-04  4:49     ` Jeffrey Carter
2005-05-04 13:45       ` Igor Khavkine
2005-05-06  3:36         ` Jeffrey Carter
2005-05-07 22:12  6%       ` igor.kh
2005-07-24 18:15     ++ of C in ada nicolas.b
2005-07-25 13:18  5% ` Marc A. Criley
2006-02-21 14:37     binding to C: popen Poul-Erik Andreasen
2006-02-21 15:25     ` jimmaureenrogers
2006-02-21 15:45       ` Poul-Erik Andreasen
2006-02-21 16:12  6%     ` Alex R. Mosteo
2006-07-28 11:06     How to pass two dimensional arrays to C Jerry
2006-07-28 12:27  7% ` Dmitry A. Kazakov
2006-08-02  8:20  6% ` Jerry
2006-08-02  9:03  0%   ` Dmitry A. Kazakov
2006-08-02 10:22  0%     ` Jerry
2006-08-02 18:25  0%   ` Björn Persson
2006-08-05  1:03  5% ` Jerry
2006-11-12  3:45     How to use Annex G.3 Vectors and Matrices in bindings to C arrays Jerry
2006-11-12 19:39     ` Jeffrey R. Carter
2006-11-13 11:20  4%   ` Jerry
2006-11-13 19:09  0%     ` Jeffrey R. Carter
2007-11-26 15:44     Variable list parameters shaunpatterson
2007-11-26 16:52     ` Steve
2007-11-26 19:00       ` Robert A Duff
2007-11-28  8:48  6%     ` axtens
2008-05-19  9:38     Pointer Sébastien
2008-05-19  9:53     ` Pointer Dmitry A. Kazakov
2008-05-19 10:13       ` Pointer Sébastien
2008-05-19 10:34         ` Pointer Ludovic Brenta
2008-05-19 11:31           ` Pointer Sébastien
2008-05-19 12:09  6%         ` Pointer Dmitry A. Kazakov
2008-05-19 12:47  0%           ` Pointer Sébastien
2008-06-27  1:39     Ada array vs C pointer (call by reference) Adrian Hoe
2008-06-28  1:21  6% ` anon
2008-08-28  7:28     Possible compiler bug with this simple program Jerry
2008-08-28  8:03     ` Niklas Holsti
2008-08-28 21:01       ` Randy Brukardt
2008-08-28 21:29         ` Jerry
2008-08-30  1:00           ` Randy Brukardt
2008-08-30  4:47             ` Jerry
2008-09-01 11:19               ` Jerry
2008-09-03  4:22                 ` Jerry
2008-09-03 14:20                   ` Adam Beneschan
2008-09-04  0:22                     ` Jerry
2008-09-04  1:31                       ` Jeffrey R. Carter
2008-09-04 14:35                         ` Adam Beneschan
2008-09-04 14:42  5%                       ` Jacob Sparre Andersen
2008-09-12  8:35     Adding offset to 'Address Kim Rostgaard Christensen
2008-09-12  9:47  4% ` Georg Bauhaus
2008-09-12 10:17  0%   ` Kim Rostgaard Christensen
2008-09-12 11:18  0%     ` petter_fryklund
2008-12-04 20:47     A curiosity mockturtle
2008-12-04 21:17     ` Adam Beneschan
2008-12-04 21:48       ` Hyman Rosen
2008-12-04 22:04         ` Ludovic Brenta
2008-12-05  9:03  4%       ` Georg Bauhaus
2009-02-14  6:58     Converting pointers to non nul-terminated C "strings" to Ada string xorquewasp
2009-02-14  9:26  6% ` Dmitry A. Kazakov
2009-02-14 10:38  0%   ` xorquewasp
2009-02-14 11:16  4%     ` Dmitry A. Kazakov
2009-02-14 11:37  0%       ` xorquewasp
2009-03-10 21:26     Representing image data Kenneth Almquist
2009-03-11  1:16     ` Gautier
2009-03-11 21:12  4%   ` Kenneth Almquist
2009-09-20 19:38     calling ada from c with an array param Mike
2009-09-21  8:04  6% ` Dmitry A. Kazakov
2009-10-20 13:07  6% Ada to C interfacing with access on unconstrained array dhenry
2009-10-20 16:24  0% ` Adam Beneschan
2011-04-16 17:02     Fun with C George P.
2011-04-17 19:19     ` Elias Salomão Helou Neto
2011-04-20  5:11       ` J-P. Rosen
2011-04-20 19:04         ` Vinzent Hoefler
2011-04-20 21:09  4%       ` Georg Bauhaus
2011-06-07 15:32     using `use' : what is the best practice ? milouz
2011-06-08  4:25     ` Jerry
2011-06-08  9:31       ` milouz
2011-06-08 19:22  4%     ` Pascal Obry
2011-08-29 15:46     Address and bit mask milouz
2011-08-29 19:41     ` Ludovic Brenta
2011-08-29 19:54       ` Adam Beneschan
2011-08-30  9:14         ` milouz
2011-08-30 12:35  5%       ` Georg Bauhaus
2011-11-07 20:09     Memory Access awdorrin
2011-11-07 21:26  4% ` Simon Wright
2013-07-01  9:02     Thick bindings to a C library and gnattest: suggestions? ziotom78
2013-07-01  9:45  6% ` Dmitry A. Kazakov
2013-07-01 11:11  3%   ` Maurizio Tomasi
2013-07-01 12:32  0%     ` Dmitry A. Kazakov
2014-05-19 22:26     How to import C pointers to structures? Victor Porton
2014-05-19 22:33     ` Shark8
2014-05-19 22:44       ` Adam Beneschan
2014-05-20  0:10  4%     ` Shark8
2014-05-20  0:22  5%       ` Adam Beneschan
2014-05-20 10:22  4% abstract types and subprograms Victor Porton
2014-05-20 11:55  0% ` Dmitry A. Kazakov
2014-05-20 12:28  0%   ` Victor Porton
2014-07-21 23:44     How to convert a C "char *" value to Ada string? Victor Porton
2014-07-22  0:28  6% ` Randy Brukardt
2016-05-02 16:45  4% A suggestion about interfacing with C mockturtle
2016-05-02 19:07  0% ` Jeffrey R. Carter
2016-05-02 19:40  0% ` Per Sandberg
2017-03-17 21:12     Interfaces.C questions hreba
2017-03-18 23:24     ` Leo Brewin
2017-03-19 12:17  4%   ` hreba
2017-03-20  9:44  0%     ` Leo Brewin
2017-03-23  7:43     Interfaces.C + generics: stack overflow hreba
2017-03-23 20:03     ` Randy Brukardt
2017-03-24 12:42       ` hreba
2017-03-24 22:03         ` Dmitry A. Kazakov
2017-03-25 14:17           ` hreba
2017-03-25 15:23  4%         ` Dmitry A. Kazakov
2017-07-07 21:03     Convert chars_ptr to Ada String Victor Porton
2017-07-07 22:23     ` Anh Vo
2017-07-07 22:48  5%   ` Victor Porton
2017-07-07 23:14  0%     ` Anh Vo
2017-07-09  6:49  0%       ` Victor Porton
2017-07-10  4:58  0%         ` Anh Vo
2017-07-10  9:31  0%           ` Victor Porton
2017-07-10  9:48                 ` Dmitry A. Kazakov
2017-07-10 12:41  5%               ` Mark Lorenzen
2017-07-10 14:24  4%                 ` Dmitry A. Kazakov
2017-08-04 22:17     Convert an access to constant to access to variable Victor Porton
2017-08-05 17:27     ` Stephen Leake
2017-08-05 17:41       ` Victor Porton
2017-08-07 23:16  6%     ` Randy Brukardt
2018-08-11  1:06     AdaCore Community 2018 Bugs Roger
2018-08-11  8:42     ` Jeffrey R. Carter
2018-08-11 12:19       ` Roger
2018-08-11 17:20         ` Simon Wright
2018-08-12  1:50           ` Roger
2018-08-12  7:33             ` Simon Wright
2018-08-12 11:45               ` Roger
2018-08-12 16:37  6%             ` Simon Wright
2018-08-13  2:02  4%               ` Roger
2018-08-13  2:54  0%               ` Roger
2020-05-05 11:04     How can one record component be local and another not? hreba
2020-05-05 15:45     ` Jeffrey R. Carter
2020-05-05 17:17       ` hreba
2020-05-05 19:08         ` Niklas Holsti
2020-05-06 19:31  3%       ` hreba
2020-12-28  9:44  4% Messing with access types Marek
2020-12-28 10:14  6% ` Dmitry A. Kazakov
2020-12-28 11:43  5%   ` Marek
2020-12-28 13:56  0%     ` Dmitry A. Kazakov

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