IDL Call External
 
IDL Call External is essentially the opposite of Callable IDL.  With Call External, you start in IDL and the IDL program calls a Fortran subroutine.  As in Callable IDL, it is useful to use a C program to go between IDL and Fortran (because of null-terminated strings, etc.).

The example shown here is the same example, align, that has been used to demonstrate re-writing in IDL and for Callable IDL.



The Fortran subroutine to be called (filename is subalign.f) is:

      SUBROUTINE subalign(XP, Y1, Y2, Y3, Y4, Y5, JMAX, EX, DEX)
      DIMENSION Y1(JMAX),Y2(JMAX),Y3(JMAX),Y4(JMAX),Y5(JMAX),XP(JMAX)
      DO 15 J=1,JMAX
      X1=EX
      X2=EX/2.
      X3=EX/3.
      X4=EX/4.
      X5=EX/5.
      Y1(J)=X1*(2.+X1)/(1.+X1)**2
      Y2(J)=X2*(2.+X2)/(1.+X2)**2
      Y3(J)=X3*(2.+X3)/(1.+X3)**2
      Y4(J)=X4*(2.+X4)/(1.+X4)**2
      Y5(J)=X5*(2.+X5)/(1.+X5)**2
      XP(J)=EX
 15   EX=EX+DEX
      RETURN
      END



The C program which serves as the go between from IDL to Fortran is align.c.  Note that this is slightly different than Callable IDL where the C wrapper always is the same and never needs to be changed.  Here, the C program must be modified to meet the needs of this particular example.
#include <stdio.h>

void subalign(int argc, void *argv[])
{
 extern void subalign_(); /* Fortran routine */
 float *xp, *y1, *y2, *y3, *y4, *y5, *ex, *dex;
 int *jmax;

 xp = (float *) argv[0]; /* Array pointer */
 y1 = (float *) argv[1]; /* Array pointer */
 y2 = (float *) argv[2]; /* Array pointer */
 y3 = (float *) argv[3]; /* Array pointer */
 y4 = (float *) argv[4]; /* Array pointer */
 y5 = (float *) argv[5]; /* Array pointer */

 /* Do the calculations in Fortran */
 subalign_(xp, y1, y2, y3, y4, y5, jmax, ex, dex);
}



When you have both the Fortran and C programs ready in a directory you must compile them.  Here is a Makefile which is designed for this example:
subalign.so : align.o subalign.o

subalign.o : subalign.f
 f77 -o32 -c subalign.f -lm -lc

align.o : align.c
 cc -o32 -c align.c

clean:
 rm -f *.o align subalign so_locations *.so



After the two programs have been compiled, you must create shared libraries.  One command must be issued to create the shared libraries.  Rather than remember what to type, I put the command in a short script named "aftermake" to remind me to use it after compiling with the Makefile.
#!/bin/csh -f
cc -o32 -shared -all subalign.o align.o -o subalign.so


Now that the files to be called by IDL are ready, enter the IDL environment by typing IDL on the command line.  For this example, the IDL program which is going to call Fortran to do some calculations, then plot the calculated data is alignp.pro
PRO alignp

JMAX = 80
EX = 0.0
DEX = 0.1
Y1 = FLTARR(JMAX)
Y2 = FLTARR(JMAX)
Y3 = FLTARR(JMAX)
Y4 = FLTARR(JMAX)
Y5 = FLTARR(JMAX)
XP = FLTARR(JMAX)

S = CALL_EXTERNAL('subalign.so', 'subalign', $
    XP, Y1, Y2, Y3, Y4, Y5, JMAX, EX, DEX)

PLOT, XP, Y1, $
   XTITLE = 'INCIDENT ENERGY (EV)', $
   YTITLE = 'T TO V EFFICIENCY', $
   PSYM = 0, $
   XSTYLE = 1, XRANGE = [0,8], $
   YSTYLE = 1, YRANGE = [0,1], $
   XTICKS = 4, XMINOR = 10, $
   YTICKS = 10, $
   CHARSIZE = 1

OPLOT, XP, Y2
OPLOT, XP, Y3
OPLOT, XP, Y4
OPLOT, XP, Y5

END

As long as the Fortran and C files have been compiled, at this point, you simply compile and run the IDL program as you would any other:
 
IDL> .rnew alignp.pro
IDL> alignp