I'm writing the Fortran bindings for a static library written in C++. This will be distributed with the library (both open source). The bindings consist of modules containing interface blocks and no executable code. The question is: Should the modules be compiled with the library (possibly at the user's request through the makefile), or should the user be required to INCLUDE the source code? What is a common/recommended practice?
Thanks.
-
1Which way would be better for your user?Robert Harvey– Robert Harvey06/28/2016 18:04:32Commented Jun 28, 2016 at 18:04
-
I'm not sure. The target audience is the casual programmer doing some minor programming probably for academic purposes. The user will have to know how to link their code to a static library. If the Fortran modules are compiled beforehand, the user will also have to know how to use additional compiler directives to find the mod files and also link to an additional library. Maybe this becomes a little too complicated but then again this can all be explained in the documentation. I wonder what other things should I consider.booNlatoT– booNlatoT06/28/2016 20:45:34Commented Jun 28, 2016 at 20:45
-
How do you currently support the possibility of multiple C++ compilers?IanH– IanH06/28/2016 22:10:50Commented Jun 28, 2016 at 22:10
-
@IanH Right now I don't. I was considering that Fortran bindings would only be available if there is a pair of "companion" Fortran and C "processors". Tested pairs would then be included in the makefile. I still don't know how to proceed with the modules, though. I understand they are susceptible to changes even in compiler version number, but then even the object files are not guaranteed to work, afaik.booNlatoT– booNlatoT06/28/2016 22:29:41Commented Jun 28, 2016 at 22:29
1 Answer 1
I would strongly recommend not to expose modules since the .mod
files are specific to the compiler.
Suppose you compile code A with GNU Fortran and code B with Intel Fortran, if these 2 codes need your library you will have to make 2 versions of the library, each one compiled with the proper compiler.
I have made this mistake in the past and it becomes a nightmare when the number of dependencies and the number of implied codes becomes large. We wrote an I/O library (Q5Cost) encapsulating HDF5. Both Q5Cost and HDF5 expose modules, so to use a code with Q5Cost we had to compile with the same compiler the code, Q5Cost and also HDF5. At some point, we would have been happier to do a module load hdf5
on the cluster or a sudo apt get install libhdf5
on the desktop since compiling HDF5 was taking much longer than compiling our codes and libraries.
So the solution is to do not like this:
module some_module
...
contains
subroutine sub1(..)
end subroutine
subroutine sub2(..)
end subroutine
...
end module
But to do like this instead:
module some_module
...
contains
...
end module
subroutine sub1(..)
use some_module
...
end subroutine
subroutine sub2(..)
use some_module
...
end subroutine
In that case, your subroutines/functions will be accessible only via the .o
files (or .a
or .so
) which are not compiler specific, and the module file will not be needed.
Also, it exposes an interface very close to the C interface which will be very simple to interface with other languages.
So please, avoid modules with libraries!
-
Note that if you expose a standard C interface in your C++ code via the
extern C { ... }
construct, it will be easy to use in Fortran withiso_c_binding
and you will not need to write a single line of Fortran.Anthony Scemama– Anthony Scemama06/28/2016 21:09:21Commented Jun 28, 2016 at 21:09 -
Yes, I do the interop in the standardized way (with iso_c_binding). I'm not sure I understand your example. As I understand it, the main difference between the two cases is that sub1 and sub2 won't have their interfaces automatically generated in the latter. So the user will either have to declare them manually, or import (via USE statement) them from a module where they are declared (or use them with implicit interfaces). And then we are back to the beginning. No? Thanks for any help!booNlatoT– booNlatoT06/28/2016 21:24:11Commented Jun 28, 2016 at 21:24
-
1Careful - it depends on the specifics of the code (e.g. use of IO, nature of the interfaces to the procedures), but in many cases the object code is also compiler specific, even if things link successfully.IanH– IanH06/28/2016 21:26:24Commented Jun 28, 2016 at 21:26
-
@booNlatoT No, the user will not have to import the module as it is imported in sub1 and sub2. The user will just
call sub1(...)
with an implicit interface and that's it. If you want to help the user by giving the interface, you can generate files containing the interface definitions that will be included (the equivalent of.h
in C).Anthony Scemama– Anthony Scemama06/28/2016 22:22:33Commented Jun 28, 2016 at 22:22 -
Then we are back to the OP. The question is really that. Should I compile modules containing the interfaces or have the user include them as source code? Using implicit interfaces is what is being avoided. Per your comment, let the user include them as if they were header files is an approach. I think I'll end doing just that. It is simple and the compiler the user is using to generate their Fortran code will handle the modules as it sees fit.booNlatoT– booNlatoT06/28/2016 22:40:50Commented Jun 28, 2016 at 22:40