How to link an external subroutine to the main program in Fortran?
Although, I got an answer from the book with the title of "Fortran 90 for scientists and engineers"
as following:
Note also that, since an external subprogram resides in a separate
file from the main program, it must be compiled separately. Under
FTN90 an intermediate type of machine code, called relocatable binary
is produced in a file with the .OBJ extension. This in turn must be
linked with the calling program by means of a special program called a
linker, finally resulting in a .EXE version of the main program. Your
compiler manual will have the details of how to do this. Once it is
finally debugged, an external subprogram need never be recompiled,
only linked. This prevents you from wasting time in compiling it over
and over, which would be the case if it was an internal subprogram.
Anyway I did not find any manual for how to link the main and subroutine programs. I use Silverfrost (Plato) to debug and run the programs. Besides, I have installed the "Intel Parallel Studio XE 2011" on the system.
For the time being I am going to assume that the external subprogram (function or subroutine) is in the same directory as the main program. In the days of fortran77 or earlier you would just call the subroutine from the main program and link them with a COMMON statement that existed both in the main program and the subprogram. However, now days the preferred method is to write your external subprograms into modules and link the module with a USE statement. For example lets make up a fictional subprogram that read in a value of 'x' and worked on it to feed back values of 'y' and 'z' to the main program. The program and module might look like the example below. A Module in essence i fortran attempt at becoming somewhat object oriented as it ensures that data is encapsulated to the programs and is not globally accessible unless the programmer wants it to be global. It is important that the programmer declare a subprogram as PRIVATE, if it is only to be called by other programs in the module and PUBLIC if it is to be called by the main program. Also in order to ensure that data is used properly, you should declare it as INTENT(IN), INTENT(OUT) or INTENT(INOUT) if the variable is only being fed into the routine, out of the routine or will be called tot he routine, worked on and fed back to the main program. I hope this helped, if not feel free to ask any other questions. Also when compiling a main program with external subprograms call them in order of subprograms to program. This means do not use ifort main.f90 module.f90, instead you must type fort module.f90 main.f90 assuming you are using an intel compiler, if not then replace fort with whatever command is used for your compiler.
PROGRAM MAIN
USE Test
IMPLICIT NONE
REAL :: X,Y,Z
X = 5.0
WRITE(*,*) X,Y,Z
END PROGRAM MAIN
MODULE Test
PUBLIC :: Subroutine_Example
CONTAINS
SUBROUTINE Subroutine_Example(X,Y,Z)
REAL, INTENT(IN) :: X
REAL, INTENT(OUT :: Y,Z
Y = X + 34.6
Z = X - 1.4
END Subroutine_Example
END MODULE Test
Related
I have some C code that I compile to a dll object.
I have a separate project, written in Fortran, which I too compile to a single dll object.
I need to call a function inside the Fortran dll from the C dll, without using LoadLibrary. I also need the 2 dll to remain separate, so I can replace one or the other without re-compiling them together.
I have read some information on the topic, but I can't get it to work. The compiler does not throw errors or warnings, but when I start my main program it fails. Here's what I tried:
I have declared all functions I wish to call from the C code with BIND ("C", NAME="FUNCNAME")
I have declared the USE, INTRINSIC :: ISO_C_Binding inside the
functions and subroutines I intend to call from the C code
I included !DEC$ ATTRIBUTES DLLEXPORT :: NAME inside the Fortran
code (I am using ifort)
I use c type variables in my Fortran code
I pass variables by reference in the C code
I included the Fortran dll .lib file as a source file to the C project
According to most sources and docs I consulted, I should be able to simply do the following:
In Fortran:
SUBROUTINE FORTRANDLLFUNCTION(arg1, arg2, arg3, char1) BIND (C, NAME='FORTRANDLLFUNCTION')
USE, INTRINSIC :: ISO_C_Binding
IMPLICIT NONE
!DEC$ ATTRIBUTES DLLEXPORT :: FORTRANDLLFUNCTION
REAL(C_FLOAT), INTENT(INOUT) :: arg1
REAL(C_FLOAT), INTENT(INOUT) :: arg2
REAL(C_FLOAT), INTENT(INOUT) :: arg3
CHARACTER(KIND=C_CHAR), INTENT(IN ) :: char1
<do stuff>
END SUBROUTINE FORTRANDLLFUNCTION
In C:
extern void FORTRANDLLFUNCTION(float**, float**, float**, char*, int);
float a, b, c;
char abc;
FORTRANDLLFUNCTION(&a, &b, &c, abc, sizeof(abc));
However, I get an error when running the main program. If I remove the call to the Fortran function and run the main program with the compiled C dll, it works. What could be the source of my problem?
This is the output of dumpbin /exports on the compiled Fortran dll:
And this is the result of dumpbin /imports on the compiled C dll:
So I finally found the cause of my problems...
I abandoned this and focused on a different part of the project, which led me to finding out that the reason why I was getting this error is that the Fortran dll didn't have to be in the same dir as the C dll, but the same dir as the exe calling the C dll (the C dll being in a different location).
It really surprises me as the error I was getting was "Can't load C.dll", instead of "Could not find/load fortran.dll", the correct traceback or message could have saved me hours...
Either ways, I believe it wouldn't have worked anyways had it not been for the comments made by #Mgetz, so thanks for that, really!
Some more clarifications to some of the comments on the question:
Before I finally realized what the solution was, and on top of creating my VS projects using cmake .. -G "Visual Studio 17 2022" -A x64, I also performed a dumpbin /headers on both the Fortran dll and the C dll, which both revealed that the machine was 8664 (64 bits architecture).
I use float** and int** in the Fortran dll function prototype in the C code because I call the Fortran function from within a C function which already takes pointers as arguments, so if I don't use "double pointers" when calling the Fortran function I get warnings from the compiler.
And yes, the Fortran runtime libraries were in the environment, I regularly work with Fortran, I knew that was not an issue.
If I have a Fortran subroutine which takes a Fortran IO Unit as one of its parameters (for printing debug information to), and this function is compiled into a shared library, how do I correctly call this function from C?
! An example subroutine that I want to call from C:
subroutine hi(unit)
integer :: unit
write(unit,*) "hello"
end subroutine
! example call site in Fortran
program main
call hi(6)
end
I am interested in how these unit numbers relate to file descriptors.
This is completely compiler dependent, there is no portable correspondence. See the manual of your compiler if they support some sort of interoperability as an extension.
I have put several subroutines into .f95 file, compiled it withgfortran -shared -fPIC -o bin/Debug/libpr10.so main.f95, now I want to use some of subroutines from that library in my C program. How do I do that (syntactically)? Do I have to produce any "headers" in Fortran library where I should declare the subroutines I want to use outside of the library (as I would have to if it was C)?
If I just tell the linker where the library is and try to call any subroutines in main() i get an error
UPDATE I don't want to mix fortran and C! I just want to use one subroutine from Fortran shared library, even w/o arguments. Despite that I have pointed out a path to the .so library, it's "invisible" for C program! The question is how to tell C program that there actually IS a subroutine that I want to invoke.
If I'm violently mistaken with "mixing" idea, correct me.
Ok, I don't think that this solution is universal but for Microsoft Visual Studio it should be __stdcall before subroutne name, and for gcc it should be a _ symbol after subroutine name e.g. we want to call subroutine called menu, so we put menu_(); into main function.
I have a C function,
double* foofunc()
{
/* Function Body */
}
I don't know how to declare an interface in Fortran to call this C function.
Also if a pointer is supposed to be pointing to GPU device memory, how could I define that in the Fortran interface? Do I need to use DEVICE attribute.
Please use features supported by Fortran up to 2003.
Any suggestions?
Since you have Fortran 2003, the easy way to interface Fortran and C is to use the ISO C Binding. (Most Fortran 95 compilers now support the ISO C Binding, even if they aren't full Fortran 2003 compilers.) This is far, far better than the complicated methods suggested in an earlier answer, which were necessary in an earlier era -- it is part of the language and therefore portable, and compiler and platform independent. But the Fortran 2003 version doesn't cover ever possibility. (The next Fortran will add additional cases of interfacing to C.) You can easily pass an argument that is a C pointer -- just leave off the "value" atttribute in the Fortran declaration. A pointer to a pointer needs C_PTR. I don't know about a pointer as a function return... I will have to experiment when I have time. If you have to, make a trivial C glue routine that converts the pointer of the function return into an argument -- that case is easy.
Re a pointer to GPU device memory -- unless your compiler has a non-standard feature, it won't have "DEVICE". Perhaps "volatile" will help? Create an appropriate user-defined type...
There are examples in the gfortran manual under "Interoperability with C". Since this is part of the language, this documentation should help even if you aren't using gfortran.
As M. S. B. said, using the fortran 2003 C interoperability features is easiest.
Simply declare the function result as type(c_ptr), and transform it to a fortran pointer by calling c_f_pointer.
The following simple example works when compiled with:
gfortran foo.f03 foofunc.c -o foo.exe
(gfortran version 4.5.0)
Contents of foo.f03:
program foo
use, intrinsic :: iso_c_binding, only : c_ptr, &
c_f_pointer, &
c_double
implicit none
type(c_ptr) :: c_p
real(c_double), pointer :: f_p
interface
function foofunc() bind(c)
import :: c_ptr
implicit none
type(c_ptr) :: foofunc
end function foofunc
end interface
c_p = foofunc()
call c_f_pointer(c_p, f_p)
print *, f_p
end program foo
Contents of foofunc.c:
double bar = 2;
double *foofunc()
{
return &bar;
}
I don't know how well it will work with a pointer to GPU device memory, though. Never dealt with that.
You want to call a C function from Fortran Program. There are many ways.
One way is to translate the C routine to fortran. If your C program is long, complex, and well tested then it may not be easy option for you. The other way is to convert the fortran to C. There may be similar problem to you.
If you can not skirt the problem as above, then you have to face the problem as below.
In programming parlance it is called Mixed Language Programming.
I do not know what version of which language and OS U are using. So instead of giving a ready made solution I shall give you four alternative approaches below. I have used all in implemented applications. The first two are for those lucky having a powerful OS ( a rare commodity now ). The program runs fast in both and suitable for hard real time jobs. The last two are for any OS, but program runs slow, particularly if C routine is called frequently. You also have to do little more programming work in all approaches. Be also aware that your C function returns a pointer in each of the alternatives.
Some fortran compilers ( not all ) allow calling a non-fortran function. This requires appropriate facilities in the OS where both fortran and C are running. In such cases identical stack management is used during procedure call. Read the programmers manual of both languages and code appropriately.
If this is not possible then you can trick the OS to do so but you need an intermediate function written in Assembler. You call assembler routine from fortran and then call the C routine from assembler and return in reverse manner. You need to know stack management details of all three that is of Fortran, Assembler and C and write a code for translating fortran stack to C stack. This will be in the assembler routine.
In both above approaches you have to be aware how your Linker ( or Binder ) works and you may have to do some extra job there. In either case it will be same .exe file so your program will run fast. In such OS’s any languages, strange to each other, can be mixed. Even DLL’s can be used. Only complexity comes if the run time library uses a fortran function having same name as a C function but doing different jobs. An OS supporting mixed language programming generally gives you some tools of preventing this.
If above alternatives are not feasible, then make both fortran and C programs as separate .exe and run both as two concurrent processes. ( note they can be in same computer or in different computers under different OS even ! ). Now whenever you need to call C from fortran, pass all parameters and data though any interprocess communication mechanism available to you, say pipe, socket or whatever it is. The C program can return data by similar mechanism. Be sure to add appropriate code for handling parameter passing through interprocess communication. Synchronisation of two processes and distinguishing old data from recent data is also your job. Stack management is not required.
This one is for those who dislike stack, synchronization, linker or anything that requires intelligence. Programs will run slowest if the C program has to be called frequently. Counter-intuitively, if the C program has to be called once only, then this becomes most intelligent solution too! Output data from fortran program to disk ( flat file or data-base ). Then call the C program to read from same file and return data to fortran in same manner. Be careful about closing the file before change of language. Handle all errors in file input-output calls. Else you crash.
I am trying to fully understand the process pro writing code in some language to execution by OS. In my case, the language would be C and the OS would be Windows. So far, I read many different articles, but I am not sure, whether I understand the process right, and I would like to ask you if you know some good articles on some subjects I couldn´t find.
So, what I think I know about C (and basically other languages):
C compiler itself handles only data types, basic math operations, pointers operations, and work with functions. By work with functions I mean how to pass argument to it, and how to get output from function. During compilation, function call is replaced by passing arguments to stack, and than if function is not inline, its call is replaced by some symbol for linker. Linker than find the function definition, and replace the symbol to jump adress to that function (and of course than jump back to program).
If the above is generally true and I get it right, where to final .exe file actually linker saves the functions? After the main() function? And what creates the .exe header? Compiler or Linker?
Now, additional capabilities of C, today known as C standart library is set of functions and the declarations of them, that other programmers wrote to extend and simplify use of C language. But these functions like printf() were (or could be?) written in different language, or assembler. And there comes my next question, can be, for example printf() function be written in pure C without use of assembler?
I know this is quite big question, but I just mostly want to know, wheather I am right or not. And trust me, I read a lots of articles on the web, and I would not ask you, If I could find these infromation together on one place, in one article. Insted I must piece by piece gather informations, so I am not sure if I am right. Thanks.
I think that you're exposed to some information that is less relevant as a beginning C programmer and that might be confusing you - part of the goal of using a higher level language like this is to not have to initially think about how this process works. Over time, however, it is important to understand the process. I think you generally have the right understanding of it.
The C compiler merely takes C code and generates object files that contain machine language. Most of the object file is taken by the content of the functions. A simple function call in C, for example, would be represented in the compiled form as low level operators to push things into the stack, change the instruction pointer, etc.
The C library and any other libraries you would use are already available in this compiled form.
The linker is the thing that combines all the relevant object files, resolves all the dependencies (e.g., one object file calling a function in the standard library), and then creates the executable.
As for the language libraries are written in: Think of every function as a black box. As long as the black box has a standard interface (the C calling convention; that is, it takes arguments in a certain way, returns values in a certain way, etc.), how it is written internally doesn't matter. Most typically, the functions would be written in C or directly in assembly. By the time they make it into an object file (or as a compiled library), it doesn't really matter how they were initially created, what matters is that they are now in the compiled machine form.
The format of an executable depends on the operating system, but much of the body of the executable in windows is very similar to that of the object files. Imagine as if someone merged together all the object files and then added some glue. The glue does loading related stuff and then invokes the main(). When I was a kid, for example, people got a kick out of "changing the glue" to add another function before the main() that would display a splash screen with their name.
One thing to note, though is that regardless of the language you use, eventually you have to make use of operating system services. For example, to display stuff on the screen, to manage processes, etc. Most operating systems have an API that is also callable in a similar way, but its contents are not included in your EXE. For example, when you run your browser, it is an executable, but at some point there is a call to the Windows API to create a window or to load a font. If this was part of your EXE, your EXE would be huge. So even in your executable, there are "missing references". Usually, these are addressed at load time or run time, depending on the operating system.
I am a new user and this system does not allow me to post more than one link. To get around that restriction, I have posted some idea at my blog http://zhinkaas.blogspot.com/2010/04/how-does-c-program-work.html. It took me some time to get all links, but in totality, those should get you started.
The compiler is responsible for translating all your functions written in C into assembly, which it saves in the object file (DLL or EXE, for example). So, if you write a .c file that has a main function and a few other function, the compiler will translate all of those into assembly and save them together in the EXE file. Then, when you run the file, the loader (which is part of the OS) knows to start running the main function first. Otherwise, the main function is just like any other function for the compiler.
The linker is responsible for resolving any references between functions and variables in one object file with the references in other files. For example, if you call printf(), since you do not define the function printf() yourself, the linker is responsible for making sure that the call to printf() goes to the right system library where printf() is defined. This is done at compile-time.
printf() is indeed be written in pure C. What it does is call a system call in the OS which knows how to actually send characters to the standard output (like a window terminal). When you call printf() in your program, at compile time, the linker is responsible for linking your call to the printf() function in the standard C libraries. When the function is passed at run-time, printf() formats the arguments properly and then calls the appropriate OS system call to actually display the characters.