- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have inherited some FORTRAN code which makes calls to routines written in 'C' and I keep running into runtime errors where parameters are passed or interpreted incorrectly. I have tried using 'INTERFACE' in the FORTRAN code to ensure parameters are passed consistently but it appears that the INTERFACE needs to be declared in every FORTRAN subroutine that makes the calls to 'C'. If you forget to include it, the code compiles but crashes at run-time because it reverts to the default (by ref) calling convention. This is very hard with large programs and is prone to human error. Is there a way to ensure that all FORTRAN subroutines use the correct calling convention without having to search through and include the INTERFACE statements? Perhaps it is better NOT to do this and to ensure that the 'C' code expects parameters to be passed by reference? This seemed like a reasonable approach to me but the FORTRAN compiler appears to allow different size INTEGERS to be passed so the 'C' code might get a pointer to an INTEGER*2 or an INTERGER*4 and BOOM! more runtime errors.
Any advice on how to do this in a consitent and robust way would be greatly appreciated. Please note that I am a C/C++ programmer and know almost zero about FORTRAN (but willing to learn)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Tony,
To expand on Tim Prince’s comments, I prefer to use MODULEs instead of INCLUDEs – the choice is yours. If you use INCLUDEs, you need to pay attention as to where you place them since it works somewhat as a preprocessor in C.
Below is some pseudo-code that shows how you can use MODULEs. You can see to Intel’s User and Reference Guide for Fortran or refer to any of the books in Dr. Fortran’s blog for details.
Say you have a C function with the following prototype:
[cpp]
int My_C_Func(char *string, int i, double d[10], void *m);
[/cpp]
You can add an interface for it in a Fortran MODULE like this:
[fortran]
MODULE Interface_to_C_Func
INTERFACE
FUNCTION Cfunc(string, i, d, p) BIND(C, NAME="My_C_Func")
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_INT, C_CHAR, C_PTR, C_DOUBLE
!.. Return value
INTEGER(C_INT) :: Cfunc
!.. Argument list
CHARACTER(KIND=C_CHAR) :: string(*)
INTEGER(KIND=C_INT), VALUE :: i
REAL(KIND=C_DOUBLE) :: d(10)
TYPE(C_PTR), VALUE :: p
END FUNCTION Cfunc
END INTERFACE
END MODULE Interface_to_C_Func
[/fortran]
You can then “use” it in your Fortran procedures as follows:
[fortran]
FUNCTION My_Fortran_Func(..)
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_INT !.. Add other objects as needed
USE Interface_to_C_Func, ONLY : Cfunc
...
INTEGER(KIND=C_INT) :: CFuncResult
...
CFuncResult = Cfunc(string, i, d, p)
...
RETURN
END FUNCTION My_Fortran_Func
SUBROUTINE My_Fortran_Routine(..)
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_INT !.. Add other objects as needed
USE Interface_to_C_Func, ONLY : Cfunc
...
INTEGER(KIND=C_INT) :: CFuncResult
...
CFuncResult = Cfunc(string, i, d, p)
...
RETURN
END SUBROUTINE My_Fortran_Routine
[/fortran]
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Take a look at the Intel Fortran samples for mixed-language programming:
User and Reference Guide for the Intel® Fortran Compiler 14.0
Using the Intel® Fortran Samples
The following applies to Fortran for Microsoft Visual Studio* 2010 and 2008.
The Intel® Fortran Compiler installs a number of sample programs. These programming samples illustrate a variety of concepts such as:
Creating console applications
Creating QuickWin applications
Creating Win32 applications
Using mixed-language support
Using OpenGL* in Fortran applications
The programming samples are located in the<install-dir>\Samples\ directory. These samples have associated build files that use the Intel® Fortran Compiler, in command-line mode, to compile and build the Fortran sources.
For further information on the samples and how to use them, use a web browser to open and read the samples.htm document in the \Samples\ folder.
Parent topic: Using Microsoft* Visual Studio* (Windows* OS)
Also, look at the documentation in "User and Reference Guide for the Intel Fortran Compiler" under Compiler Reference, Mixed Language Programming.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks FortranFan,
I have used the INTERFACE statement as shown in the samples and it works OK.But unless I am missing something, I have to include this statement in envery subroutine which calls the 'C' code. If I dont, then it reverts to calling the 'C' in the default way (arguments by ref). Since the application is quite large, consisting of may subroutines in several fines, and I did not write it, it is very difficult to catch every instance where the 'C' code is called. In 'C', I would include a header containing function prototypes at the top of every source file and the compiler would highlight 'offending' calls. I tried to put the interface definition in a file and have a single INCLUDE at the top of each fortran source file but the compiler didnt like it. It says "error #6218: This statement is positioned incorrectly and/or has syntax errors" at the first subroutine in the file. Am I doing something wrong?
Sorry but I am not en experienced FORTRAN programmer!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You're correct, the INTERFACE has to be placed at the correctly in each Fortran procedure. I would think you would try putting it in a MODULE which you can USE in each procedure, although it could be done by repeating INCLUDE if you observe the position requirements (same as if each procedure were in a separate file).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Tony,
To expand on Tim Prince’s comments, I prefer to use MODULEs instead of INCLUDEs – the choice is yours. If you use INCLUDEs, you need to pay attention as to where you place them since it works somewhat as a preprocessor in C.
Below is some pseudo-code that shows how you can use MODULEs. You can see to Intel’s User and Reference Guide for Fortran or refer to any of the books in Dr. Fortran’s blog for details.
Say you have a C function with the following prototype:
[cpp]
int My_C_Func(char *string, int i, double d[10], void *m);
[/cpp]
You can add an interface for it in a Fortran MODULE like this:
[fortran]
MODULE Interface_to_C_Func
INTERFACE
FUNCTION Cfunc(string, i, d, p) BIND(C, NAME="My_C_Func")
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_INT, C_CHAR, C_PTR, C_DOUBLE
!.. Return value
INTEGER(C_INT) :: Cfunc
!.. Argument list
CHARACTER(KIND=C_CHAR) :: string(*)
INTEGER(KIND=C_INT), VALUE :: i
REAL(KIND=C_DOUBLE) :: d(10)
TYPE(C_PTR), VALUE :: p
END FUNCTION Cfunc
END INTERFACE
END MODULE Interface_to_C_Func
[/fortran]
You can then “use” it in your Fortran procedures as follows:
[fortran]
FUNCTION My_Fortran_Func(..)
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_INT !.. Add other objects as needed
USE Interface_to_C_Func, ONLY : Cfunc
...
INTEGER(KIND=C_INT) :: CFuncResult
...
CFuncResult = Cfunc(string, i, d, p)
...
RETURN
END FUNCTION My_Fortran_Func
SUBROUTINE My_Fortran_Routine(..)
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_INT !.. Add other objects as needed
USE Interface_to_C_Func, ONLY : Cfunc
...
INTEGER(KIND=C_INT) :: CFuncResult
...
CFuncResult = Cfunc(string, i, d, p)
...
RETURN
END SUBROUTINE My_Fortran_Routine
[/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks FortranFan and Tim, your help is greatly appreciated.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page