From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,c0beb84916773d4c X-Google-Attributes: gid103376,public From: jm59@prism.gatech.edu (John M. Mills) Subject: Re: Ada-FORTRAN Interfacing [longish -- source excerpts] Date: 1998/02/25 Message-ID: <6d1dju$cnb@acmey.gatech.edu> X-Deja-AN: 328523869 References: <34F3853A.BE5172B9@dr-inc.com> Organization: Georgia Institute of Technology Newsgroups: comp.lang.ada Date: 1998-02-25T00:00:00+00:00 List-Id: Laurent Guerby writes: >Andy Willey writes: >> I am attempting to link Ada and FORTRAN modules together. I am using >> GNAT Ada and the GNU FORTRAN compiler. If anyone knows of any >> documentation or examples that specifically address the Ada-FORTRAN >> interface, please let me know. > I know there are some quite active people doing Ada/FORTRAN things, > may be they don't read comp.lang.ada anymore? I exchanged notes on this with a c.l.a. reader, and here is a summary of my linking Ada through Fortran from Ada. I think this may fairly be called a "worst case scenario" &;^) Essentially the same summary is on my anon-ftp site: ftp://jmills.gtri.gatech.edu/pub This built on various platforms with various Fortran compilers, though I have no guarantees to offer. The application will be familiar to many readers of _Numerical Recipes in *_: **** Date: Fri, 25 Jul 1997 09:49:50 -0400 (EDT) From: "MILLS,JOHN M." To: **** Subject: Re: Fortran Interfacing Reply-To: john.mills@gtri.gatech.edu > Can anybody tell me how to EXPORT from Ada to fortran. I have > a large program written in fortran and wish to include it in an Ada > program. I think I can manage the import quite easily (there are > plenty of examples around, and I have managed on a test program), > but I cannot manage the export (there are NO examples I can find and > I can't manage a test program). > > If someone could write/ or explain how I could write, a small test > program that called a Fortran subroutine that in turn called an Ada > program I would be very grateful. -- I coded a case where I called a Fortran subroutine from a GNAT-3.05 Ada main, and passed to the subroutine pointers ('access procedure') to both Fortran and Ada subroutines. The Ada pointer was in its turn passed to the Fortran subroutine identified by its pointer. Vectors of LONG_FLOATs were also passed from Fortran to Ada and back. There are probably a few more possible paths, but I would say that was a start. I took four steps to do this: 1) I provided an Ada specification for the Fortran routines, and 2) I provided a "shim" called by Fortran which called my Ada with appropriate data types, 3) I exported the entries of the Ada routines as Fortran, and 4) I had to provide a global Ada variable as a "selector" which was set in Ada before calling the Fortran, then checked in Ada called from Fortran. (This was due to my Ada code design, and allowed the passing of strictly numerical data arrays among the players -- I can't guarantee re-entrancy of the result, but I was trying to trap competing calls from possible other GIMBAL objects.) You may recognize that I am using a Runge-Kutta integration patterned on the example in _Numerical_Recipes_ -- no modifications were needed in the precompiled Fortran library which was widely used by other applications. Here are the wrappers in the Ada spec for the Fortran subroutine package: ******< from ode.ads >****** with DATA_TYPES; use DATA_TYPES; package ODE is -- NMAX must stay in sync with NMAX : constant INTEGER := 20; type VAR_ARRAY is array (1 .. NMAX) of LONG_FLOAT; type DERIV_ACCESS is access -- access to Ada, used from Fortran PROCEDURE( X : in out LONG_FLOAT; Y : in out VAR_ARRAY; DYDX : in out VAR_ARRAY); pragma CONVENTION(FORTRAN, DERIV_ACCESS); type STEPPER_ACCESS is access -- access to Fortran, used from Fortran PROCEDURE( Y : in out VAR_ARRAY; DYDX : in out VAR_ARRAY; N : in out INTEGER; X : in out LONG_FLOAT; HTRY : in out LONG_FLOAT; EPS : in out LONG_FLOAT; YSCAL : in out VAR_ARRAY; HDID : in out LONG_FLOAT; HNEXT : in out LONG_FLOAT; THE_DERIVS: DERIV_ACCESS); pragma CONVENTION(FORTRAN, STEPPER_ACCESS); procedure RKQC( Y : in out VAR_ARRAY; -- Fortran used from Fortran DYDX : in out VAR_ARRAY; N : in out INTEGER; X : in out LONG_FLOAT; HTRY : in out LONG_FLOAT; EPS : in out LONG_FLOAT; YSCAL : in out VAR_ARRAY; HDID : in out LONG_FLOAT; HNEXT : in out LONG_FLOAT; THE_DERIVS: DERIV_ACCESS); pragma IMPORT(Fortran, RKQC, "rkqc_"); procedure ODEINT( YSTART : in out VAR_ARRAY; -- Fortran used from Ada NVARS : in out INTEGER; X1 : in out LONG_FLOAT; X2 : in out LONG_FLOAT; EPS : in out LONG_FLOAT; H1 : in out LONG_FLOAT; HMIN : in out LONG_FLOAT; NOK : in out INTEGER; NBAD : in out INTEGER; THE_DERIVS : DERIV_ACCESS; THE_STEPPER : STEPPER_ACCESS); pragma IMPORT(Fortran, ODEINT, "odeint_"); ********* Here is the Ada "shim" which was actually called from Fortran: ******< from my_app.adb >****** -------------------------------------------------------------------------------- -- procedure GIMBAL_DERIVS (RK_X : in out LONG_FLOAT; -- -- RK_Y : in out array (1..GIMBAL_DERIVATIVE'SIZE) of LONG_FLOAT; -- -- RK_DYDX : in out array (1..GIMBAL_DERIVATIVE'SIZE) of LONG_FLOAT) -- -- Computes derivatives of specified gimbal in its current state. -- -- GIMBAL_DERIVS provides a wrapper for GET_DERIVS for use by Fortran RK4 -- -- ODE integration library routine ODEINT2DP. -- -------------------------------------------------------------------------------- procedure GIMBAL_DERIVS (RK_X : in out LONG_FLOAT; RK_Y : in out VAR_ARRAY; RK_DYDX : in out VAR_ARRAY) is PEDESTAL_STATE : DIRCM_STATE_VECTOR := (others => 0.0); ESTIMATED_DERIVATIVES : GIMBAL_DERIVATIVE := (others => 0.0); begin PEDESTAL_STATE.AZIMUTH := RK_Y(1); PEDESTAL_STATE.ELEVATION := RK_Y(2); PEDESTAL_STATE.AZIMUTH_DOT := RK_Y(3); PEDESTAL_STATE.ELEVATION_DOT := RK_Y(4); ESTIMATED_DERIVATIVES := GET_DERIVS( SELECTED_GIMBAL, PEDESTAL_STATE, RK_X); RK_DYDX(1) := ESTIMATED_DERIVATIVES.AZIMUTH_DOT; RK_DYDX(2) := ESTIMATED_DERIVATIVES.ELEVATION_DOT; RK_DYDX(3) := ESTIMATED_DERIVATIVES.AZIMUTH_DOT_DOT; RK_DYDX(4) := ESTIMATED_DERIVATIVES.ELEVATION_DOT_DOT; end GIMBAL_DERIVS; pragma EXPORT (Fortran, GIMBAL_DERIVS, "gimbal_derivs_"); -------------------------------------------------------------------------------- ******** Here is the actual Ada call to the nested Fortran: ******< also from my_code.adb >******* -------------------------------------------------------------------------------- -- procedure INTEGRATE_GIMBAL_MOTION( THE_GIMBAL : in out GIMBAL; -- -- THE_STATE : in out DIRCM_STATE_VECTOR) -- -- wraps and invokes Fortran routines performing Runge-Kutta integration of -- -- the gimbal equations of motion in pedestal (AZ, EL) axes. -- -------------------------------------------------------------------------------- procedure INTEGRATE_GIMBAL_MOTION(THE_GIMBAL : in out GIMBAL; THE_STATE : in out DIRCM_STATE_VECTOR) is YSTART : VAR_ARRAY := (others => 0.0); NVARS : INTEGER := NMAX; X1 : LONG_FLOAT := 0.0; X2 : LONG_FLOAT := 0.0; EPS : LONG_FLOAT := 1.0; H1 : LONG_FLOAT := 0.0; HMIN : LONG_FLOAT := 0.0; NOK : INTEGER := 0; NBAD : INTEGER := 0; THE_STEPPER : constant STEPPER_ACCESS := RKQC'ACCESS; THE_DERIVATIVES : constant DERIV_ACCESS := GIMBAL_DERIVS'ACCESS; begin -- check for interfering thread if SELECTED_GIMBAL /= NULL then raise CHAINING_ERROR; end if; -- select gimbal being updated, for GET_DERIVS use SELECTED_GIMBAL := THE_GIMBAL; -- set up calling arguments for ODEINT YSTART(1) :=THE_STATE.AZIMUTH; YSTART(2) :=THE_STATE.ELEVATION; YSTART(3) :=THE_STATE.AZIMUTH_DOT; YSTART(4) :=THE_STATE.ELEVATION_DOT; NVARS := 4; X2 := THE_GIMBAL.TIME_STEP; EPS := 0.01; H1 := THE_GIMBAL.TIME_STEP; HMIN := 0.0; ODEINT( YSTART, NVARS, X1, X2, EPS, H1, HMIN, NOK, NBAD, THE_DERIVATIVES, THE_STEPPER); -- return new state of gimbal THE_STATE.AZIMUTH := YSTART(1); THE_STATE.ELEVATION := YSTART(2); THE_STATE.AZIMUTH_DOT := YSTART(3); THE_STATE.ELEVATION_DOT := YSTART(4); -- reset gimbal selection SELECTED_GIMBAL := null; end INTEGRATE_GIMBAL_MOTION; -------------------------------------------------------------------------------- ********* Note: These vectors are passed in jointly acceptable format, but if you are passing _higher_dimension_arrays_, you need to define the Ada side of the argument with a subscripting order appropriate to Fortran. This is covered in the Ada 95 LRM, and I believe the pragma is "Convention" -- I don't have it at hand to give you a reference. The same problem may arise passing data between Fortran and C, I believe, as I understand Ada95 uses the same subscript ordering as C -- the reverse of Fortran. Regards -- jmm -- -------------------- -- John M. Mills, Senior Research Engineer -- john.mills@gtri.gatech.edu Georgia Tech Research Institute, Georgia Tech, Atlanta, GA 30332-0834 Phone contacts: 404.894.0151 (voice), 404.894.6258 (FAX) "Lies, Damned Lies, Statistics, and Simulations."