comp.lang.ada
 help / color / mirror / Atom feed
From: hreba <f_hreba@yahoo.com.br>
Subject: Re: How can one record component be local and another not?
Date: Wed, 6 May 2020 21:31:11 +0200
Date: 2020-05-06T21:31:11+02:00	[thread overview]
Message-ID: <hhghk0F702iU1@mid.individual.net> (raw)
In-Reply-To: <hhdrtkFk328U1@mid.individual.net>

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

  reply	other threads:[~2020-05-06 19:31 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-05 11:04 How can one record component be local and another not? hreba
2020-05-05 11:33 ` AdaMagica
2020-05-05 11:38   ` AdaMagica
2020-05-05 12:59   ` hreba
2020-05-05 13:19     ` J-P. Rosen
2020-05-05 13:37     ` Jere
2020-05-05 14:28       ` hreba
2020-05-05 15:18         ` AdaMagica
2020-05-05 14:32   ` hreba
2020-05-05 11:43 ` AdaMagica
2020-05-05 12:55   ` hreba
2020-05-05 11:46 ` Simon Wright
2020-05-05 13:07   ` hreba
2020-05-05 17:00     ` Dmitry A. Kazakov
2020-05-05 11:48 ` Niklas Holsti
2020-05-05 13:44   ` 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       ` hreba [this message]
2020-05-09 19:43         ` Niklas Holsti
2020-05-10 15:10           ` hreba
2020-05-05 19:19     ` Jere
2020-05-06  6:42     ` Mark Lorenzen
2020-05-06  8:26       ` Simon Wright
2020-05-06  8:33         ` Mark Lorenzen
2020-05-05 17:32 ` hreba
2020-05-05 19:04   ` Niklas Holsti
2020-05-05 20:11     ` Niklas Holsti
2020-05-06 13:13       ` hreba
2020-05-06 17:30   ` Niklas Holsti
2020-05-06 18:28     ` Jere
2020-05-06 19:09       ` Niklas Holsti
2020-05-07  9:07     ` J-P. Rosen
2020-05-07 10:15       ` Niklas Holsti
2020-05-07 13:00         ` Egil H H
2020-05-07 13:25         ` Simon Wright
2020-05-07 10:31       ` Stefan.Lucks
2020-05-07 11:58         ` J-P. Rosen
replies disabled

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