From: calvin@dinkum.wpd.sgi.com (Calvin H. Vu)
Newsgroups: comp.sys.sgi
Subject: Re: C/FORTRAN Communication Problem
Date: 1 Sep 92 15:30:42 GMT
Organization: Silicon Graphics, Inc.  Mountain View, CA

In <31751@adm.brl.mil> nobody@kodak.com writes:

| >From:	NAME: Arup K. Ghose                 
| 	FUNC: Biophys. & Compu. Chem.         
| 	TEL: (518) 445-7059                   <GHOSEAK@A1@DSRGVJ>
| To:	"info-iris@BRL.MIL"@kodakr@mrgate@wpc
| 
|           I have some problem in communication between a Fortran (calling)
|           routine and a C routine. Only speciality here is that I want to
|           keep a character variable as char* in the C routine parameter. The
|           programs are:
|           
|           prog1.f
|           
|                 integer*4 wing,item,ncall
|                 character*13 totline
|                 ncall = 5
|                 wing = 2
|                 totline(1:13)='Arup K. Ghose'
|                 write(*,'('' Main_b:: ncall&wing='',i3,2x,i3)') ncall,wing
|                 write(*,'('' Main_b:: totline ='',a)') totline
|                 item = dispmenu(wing,ncall,totline)
|                 write(*,'('' Main_a:: item&ncall&wing='',3(i3,2x))') 
|                & item,ncall,wing
|                 write(*,'('' Main_a:: totline ='',a)') totline
|                 stop
|                 end
|           
|           
|           prog2.c
|           
|           /* CENTRY */
|           int dispmenu_(wing,ncall,totline) 
|           long int wing;
|           long int ncall;
|           char *totline;     
|           {
|                long int datum;
|                printf("Dispmenu:: wing= %d \n", wing);
|                printf("Dispmenu:: ncall= %d \n",ncall);
|                printf("Dispmenu:: Totline= %s \n",totline);
|                datum = 20;  
|                return datum;
|           } /* ENDCENTRY */
|           
	There are a few bugs in the C routine:

	1) the argument WING and NCALL should be declared as 'long int *'
    since Fortran passes the arguments by reference.
	2) There should be an extra argument at the end which contains the
    length of the character string.
	3) Fortran does not guarantee character variables to be 
    null-terminated so the C routine must make sure that the string is
    null-terminated when printing it out otherwise it could exceed the
    accessible address space and cause a coredump.

    A better form of the C function is:

          int dispmenu_(wing,ncall,totline, linelen)
          long int *wing;
          long int *ncall;
          char *totline;
          long int linelen;
          {
               long int datum;
               char *format = "Dispmenu:: Totline= %         ";
               printf("Dispmenu:: wing= %d \n", wing);
               printf("Dispmenu:: ncall= %d \n",ncall);
		/* set up a variable format depending on the length of
		the character string so the following printf will only
		print upto that length
		 */
               sprintf( format+21, ".%ds \n", linelen);
               printf(format,totline);
               datum = 20;
               return datum;
          } /* ENDCENTRY */

|           
|           This program seems to me very similar to the example discussed
|           under 'Uaing mkf2c and extcentry' on page 3-16 in Fortran 77
|           Programmer's Guide. Unfortunately the comparable Makefile creates
|           the executable code without any error message, but it dumps core
|           due to Segmentation fault. 
	
	You should also look at section 3.1.2 which discusses argument
passing between C and Fortran.

|           Any help will be appreciated. Thanks,
|           
|           Arup Ghose
|           aghose@kodak.com

Hope that helps,

- calvin
--
-----------------------------------------------------------------------------
Calvin H. Vu			   | "We are each of us angels with only one
Silicon Graphics Computer Systems  | wing.  And we can only fly embracing
calvin@sgi.com   (415) 962-3679	   | each other."
Newsgroups: comp.sys.sgi