rr@linus.UUCP (Robert Rifkin) (12/28/87)
I am trying to link C code with some canned Fortran routines (the NAG math library) on a Unix-based system. I understand that Fortran subroutines pass arguments by address, so the calling C code must use addresses to be compatible. However, one snag that I still have is that the Fortran routine passes a function name through the subroutine call e.g. external function . . call x (function, a,b,c...) where "function" is the function , and a,b,and c are variables. I believe that what Fortran does is that "function" passes the address of where the actual function begins. I've tried C-code calls like double precision *functioin( ); . . x_(function, &a,&b,&c); to no avail. Does anyone have any suggestions for solving this problem? -- Robert Rifkin Phone: (617) 271-2302 The MITRE Corporation ARPA: linus!rr@MITRE-BEDFORD Bedford, MA 01730 UUCP: decvax!linus!rr
gwk@mitre-bedford.arpa (Glenn Karcher MITRE/D74) (12/29/87)
Concerning the passing of an external address, let me suggest a method that I have used in the past, namely, use a compiler option to generate the equivalent assembly language code for the FORTRAN compiler that you are dealing with (fortunately, most compilers have this option). Of course, the exact linkage mechanism is going to vary depending on the exact compiler/machine system you will be working on, and it is a bit tedious, but it does get the job done. NOTE: You might have to apply the same method to both the calling program and the called program in order to find out how each language handles the problem. As an example, I did the following on under ULTRIX (in case you hadn't read the header, I also work here at MITRE in the software center), on the MBUNIX machine. I used the "f77" command with the -S option to get the object code listing for FORTRAN. I also used the "cc" command with -S option for the C language. The following should work, as it turns out for this system, you can achieve the desired results by just passing the procedure as a parameter, without the use of indirection. The following FORTRAN program generates the assembly code that is interspersed. I cut out some of the overhead code to hopefully make it simpler: C C Test of code generation for external function call C REAL A, B, C EXTERNAL XYZ C C The offending call C CALL MYFUNC ( XYZ, A, B, C ) >> >> -- generated assembly code for FORTRAN >> >> addl3 $v.4-v.1,r11,r0 >> pushl r0 ; address of C, longword >> addl3 $v.3-v.1,r11,r0 >> pushl r0 ; address of B, longword >> addl3 $v.2-v.1,r11,r0 >> pushl r0 ; address of A, longword >> pushl $_xyz_ ; address of XYZ, longword >> calls $4,_myfunc_ ; call the function END The following C routine should represents the same calling sequence from C. main () { float A, B, C ; float xyz_ () ; /* note the procedure name to get correct characters and trailing underscore */ void MYFUNC () ; MYFUNC ( xyz_, &A, &B, &C ) ; >> >> -- generated assembly code for C >> >> subl3 $12,fp,r0 ; address of C >> pushl r0 >> subl3 $8,fp,r0 ; address of B >> pushl r0 >> subl3 $4,fp,r0 ; address of A >> pushl r0 >> pushl $_xyz_ ; address of xyz >> calls $4,_MYFUNC ; procedure call } I hope that this is the answer you needed. If there is more, please feel free to call me. I have had to do this kind of activity on a few different machines in the past, and it can be fun (strange sense of fun, isn't it). Let me know how it works out. Regards, Glenn Karcher (MITRE/D74) Phone: 377-6873 Yes, that is the base (dial 122-3-6873) from inside of MITRE.
flaps@dgp.toronto.edu (Alan J Rosenthal) (01/03/88)
In article <20615@linus.UUCP> rr@linus.UUCP (Robert Rifkin) writes: >I believe that what Fortran does is that "function" passes the address >of where the actual function begins. > I've tried C-code calls like > double precision *function( ); > . > . > x_(function, &a,&b,&c); >to no avail. I believe you might mean "double (*function)()" not "double *function()". -- "Bill Joy uses EMACS." - D. Hugh Redelmeier