[comp.lang.c] Problem calling a C function from Fortran

okinaka@ssc-vax.UUCP (Nathan Okinaka) (08/20/88)

I'd appreciate if anybody out there could help me with a problem I'm having 
calling a function written in C from a Fortran program on the VAX/VMS.

I'm passing two arguments to a C function called "test".  The first one is 
an integer*4 varaible and the second one is an external function.  The first 
argument gets passed ok but the external function "dbl" does not seem to get 
passed ok.

The C function requires the address of where the function "dbl" starts so
I'm passing the value of the address of the function "dbl" to the C function
"test" but it does not seem to work.  I'm wondering what Fortran does when you
try and get %loc(dbl).  Is this really the address of where this function 
starts?  What am I doing wrong?  Any help would be appreciatted.  This is a
test program I'm trying out which I need to use in another bigger program.

Thanks,
Nate Okinaka (206)773-2687

The following is the error message I get when I run the program:
-----------------------------------------------------------------------------
[okinaka]> r ext
%loc(dbl) =        4848
%loc(dbl) in hex =    12F0
iangle =          90
iangle in hex =      5A
This is a test of external function
x = 90, f = 4848 (decial)
x = 5a, f = 12f0 (hex)
%SYSTEM-F-ACCVIO, access violation, reason mask=00, virtual address=0000005A, 
PC=000012F9, PSL=03C00020
%TRACE-F-TRACEBACK, symbolic stack dump follows
module name     routine name                     line       rel PC    abs PC
DBL             DBL                                 5      00000009  000012F9
TEST            test                                9      00000039  000013AD
EXT$MAIN        EXT$MAIN                           17      000000AA  000012AA
-----------------------------------------------------------------------------

The following lists the Fortran program and the C function that I'm calling:
C------------------------------------------------------------------------
C	Main Fortran Program
C------------------------------------------------------------------------
	implicit none
	external dbl
	integer*4 func_adr
	integer*4 test, temp
	integer*4 dbl
	integer*4 iangle, istat

	iangle = 90
	func_adr = %loc(dbl)
	type *,'%loc(dbl) =',func_adr
	write(5,100)func_adr
100	format(' %loc(dbl) in hex =',z8)
	type *,'iangle =',iangle
	write(5,110)iangle
110	format(' iangle in hex =',z8)

	istat =  test(%val(iangle), %val(func_adr))
	type *,' '
	type *,'istat=',istat

	end

	integer*4 function dbl(x)
	implicit none
	integer*4 x
	dbl = (2 * x)
	type *,' '
	type *,'dbl> x=',x,' dbl=',dbl
	type *,' '
	return
	end

/*---------------------------------------------------------------------------*/
/* C Funtion test							     */
/*---------------------------------------------------------------------------*/
int test(x,f)
int x;
int (*f)();
{                 
        int y;
	printf("\nThis is a test of external function\n");
	printf("x = %d, f = %d (decial)\n",x,f);
	printf("x = %x, f = %x (hex)\n",x,f);
	y = (*f)(x);
	printf("y = %d\n",y);
	return(y);
}

scjones@sdrc.UUCP (Larry Jones) (08/21/88)

In article <1134@ssc-bee.ssc-vax.UUCP>, okinaka@ssc-vax.UUCP (Nathan Okinaka) writes:
< I'd appreciate if anybody out there could help me with a problem I'm having 
< calling a function written in C from a Fortran program on the VAX/VMS.

Well, the problem is actually calling a FORTRAN subroutine from C, but read on.
 
< I'm passing two arguments to a C function called "test".  The first one is 
< an integer*4 varaible and the second one is an external function.  The first 
< argument gets passed ok but the external function "dbl" does not seem to get 
< passed ok.

Sure it does, you just called it wrong.
 
< The C function requires the address of where the function "dbl" starts so
< I'm passing the value of the address of the function "dbl" to the C function
< "test" but it does not seem to work.  I'm wondering what Fortran does when you
< try and get %loc(dbl).  Is this really the address of where this function 
< starts?  What am I doing wrong?  Any help would be appreciatted.  This is a
< test program I'm trying out which I need to use in another bigger program.
< 
< Thanks,
< Nate Okinaka (206)773-2687
< 
< The following is the error message I get when I run the program:
< -----------------------------------------------------------------------------
< [okinaka]> r ext
< %loc(dbl) =        4848
< %loc(dbl) in hex =    12F0
< iangle =          90
< iangle in hex =      5A
< This is a test of external function
< x = 90, f = 4848 (decial)
< x = 5a, f = 12f0 (hex)
< %SYSTEM-F-ACCVIO, access violation, reason mask=00, virtual address=0000005A, 
< PC=000012F9, PSL=03C00020
< %TRACE-F-TRACEBACK, symbolic stack dump follows
< module name     routine name                     line       rel PC    abs PC
< DBL             DBL                                 5      00000009  000012F9
< TEST            test                                9      00000039  000013AD
< EXT$MAIN        EXT$MAIN                           17      000000AA  000012AA

Well, the traceback shows that your FORTRAN main program did call your C
function which then called the FORTRAN subroutine so that's not the problem.
The problem is that when the C function calls the FORTRAN subroutine, it passes
the VALUE of the argument instead of the ADDRESS.  When the FORTRAN subroutine
tried to access the variable, it used the value as an address and tried to
get the value stored there and that's what caused the access violation.
Just pass the address instead and everything will work fine.

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
Nancy Reagan on superconductivity: "Just say mho."

gil@limbic.UUCP (Gil Kloepfer Jr.) (08/22/88)

In article <1134@ssc-bee.ssc-vax.UUCP> okinaka@ssc-vax.UUCP (Nathan Okinaka) writes:
|>
|>I'd appreciate if anybody out there could help me with a problem I'm having 
|>calling a function written in C from a Fortran program on the VAX/VMS.
|>
 [Description deleted]
|>Thanks,
|>Nate Okinaka (206)773-2687
|>
|>The following is the error message I get when I run the program:
|>-----------------------------------------------------------------------------
|>%SYSTEM-F-ACCVIO, access violation, reason mask=00, virtual address=0000005A, 
|>PC=000012F9, PSL=03C00020
|>%TRACE-F-TRACEBACK, symbolic stack dump follows
|>module name     routine name                     line       rel PC    abs PC
|>DBL             DBL                                 5      00000009  000012F9
|>TEST            test                                9      00000039  000013AD
|>EXT$MAIN        EXT$MAIN                           17      000000AA  000012AA

[Programs deleted]

Nate,

The fact that your program aborted in DBL shows that DBL *is* actually
called (and it is, from looking at your programs).  The problem is in the
way you pass the integer*4 number to the C program.  Here is a little code
segment to show how to properly pass integer variables between fortran and
C on VMS:

Fortran code:

	PROGRAM TEST

	INTEGER*4    FVAR

	CALL CROUTINE(FVAR)

	CALL EXIT
	END

C code:

	croutine(fvar)
	long *fvar;  /* note: fortran passes by reference */
	{
		long cvar;

		cvar = *fvar + 10;  /* correct referencing of fvar */
		f77routine(&cvar);  /* must pass cvar to f77 by reference */
				    /* which is a C pointer */
	}

Fortran code:

	SUBROUTINE F77ROUTINE(CVAR)
	INTEGER*4  CVAR

	WRITE(6,*) 'CVAR = ',CVAR

	RETURN
	END

Your passing of the function with %LOC was perfect, but the way you passed
your integer variables seemed a bit obscure.  I have been using C and
FORTRAN this way with success, so this should help.

Hope it did help...

+------------------------------------+----------------------------------------+
| Gil Kloepfer, Jr.                  | Net-Address:                           |
| ICUS Software Systems              | {boulder,talcott}!icus!limbic!gil      |
| P.O. Box 1                         | Voice-net: (516) 968-6860              |
| Islip Terrace, New York  11752     | Othernet: gil@limbic.UUCP              |
+------------------------------------+----------------------------------------+

stejk@caen.engin.umich.edu (Steven J Kassarjian) (08/23/88)

In general, what happens when the caller and the subroutine
disagree as to the argument list of the subroutine.
Specifically, the main body of the program called the
subroutine like this
...
      CALL CONFUS (A, B, C)
...
while the subroutine was defined this way
      SUBROUTINE CONFUS (A, B)
....

What happened was that C was always zero, though I think that
this is due to the compiler initializing C to zero.

I am interested in what would (and probably did) happen, with
all the nitty-gritty (and dirty) details.  :-)

Also, what would happen in the reverse case (where the caller
doesn't supply an argument)?

Thanks (in advance) for the info.
steve.

p.s. how do you start a new discussion, with a new title, etc.?

                        steve kassarjian
+-----------------------------------------------------------------+
| All opinions are                        Eunichs:  the operating |
| local and undefined                                  system for |
| outside of unit.                                      real men. |
+-----------------------------------------------------------------+
                    stejk@caen.engin.umich.edu