Ferret external functions written in Python are usually much easier to write, as well as read and understand, than those written in Fortran. Hopefully any new Ferret external functions you may write will by in Python instead of Fortran. However, many sites, or just users on their own, already have a collection of custom Ferret functions written in Fortran, and have no interest in rewriting this code in Python. PyFerret can still use these Ferret Fortran external functions simply by recompiling the existing code, but linking in one additional library (the pyferret library).
Why the rebuild?
Ferret Fortran external functions call a number of subroutines defined in Ferret, such as ef_set_desc, ef_set_num_args, and ef_get_bad_flags. The names of all these subroutines begin with ef_ and, of course, in Fortran are case-insensitive. When a Ferret Fortran external function was run by the traditional Ferret executable, the ef_ subroutines were automatically recognized as subroutines in the Ferret executable itself. As such, one did not have to worry about specifying where the ef_ subroutines were located in the linking step of building a Ferret Fortran external function.
In PyFerret, however, the program now being run is Python, and the Ferret engine resides in a shared-object library, libpyferret.so, that the pyferret Python module reads and uses. Thus, when a Ferret Fortran external function is run by Ferret engine in PyFerret, the ef_ subroutines are no longer automatically found. But the solution to this problem is simply a matter of specifying where the ef_ subroutines are located.
Linking in the pyferret library
The Ferret Fortran external functions need to be rebuilt, linking in the pyferret library so that the Ferret external functions will know to look in the pyferret library to find the ef_ subroutines. There are a couple of ways of linking in the pyferret library, but probably the easiest for the gfortran compiler is to use the -L and -l (a capital and a lowercase letter ell) options. The -L option is immediately followed (no spaces) by the name of the directory containing the library, and the -l option is immediately followed (no spaces) by the base name of the library (which has the lib name prefix and the filename extension removed). So the compile and link commands would look something like the following:
gfortran -fPIC -fno-second-underscore -I${FER_DIR}/ext_func/src/ef_utility -c subtract.F -o subtract.ogfortran -fPIC -shared subtract.o -L${FER_DIR}/lib/python2.6/site-packages/pyferret -lpyferret -o subtract.so
The $FER_DIR/ext_func directory has been configured so that the appropriate -L and -l flags are assigned in the SYSLIBS value given in the $FER_DIR/ext_func/src/ef_utility/platform_specific.mk... files, one of which is included in all the Makefiles. The values given in the file $FER_DIR/ext_func/src/ef_utility/site_specific.mk, which is also included in all the Makefiles, should be checked prior to building. (If you are using python2.7, you will need to change the PYTHON_EXE value. You may also want to select a different installation directory for the Ferret Fortran external functions that will be built.) At this point, building the Ferret Fortran external functions under $FER_DIR/ext_func/src/ only require you to run make clean and then make to rebuild your external functions. Run make install to install these newly built Ferret Fortran external functions.
The -L option given above only tells the linker where the pyferret library resides. This information is intentionally not recorded in the built function (.so file) so that the function will still work if the location of the library changes. However, this means when the external function runs, the system needs to be able to find the pyferret library in one of the standard directories that is searched. This list of searched directories can be extended in Linux by adding directories (separated by colon characters ':') to the environment variable LD_LIBRARY_PATH. As of PyFerret v1.1, the ferret_paths scripts add the directory containing the pyferret library to the definition of LD_LIBRARY_PATH, and so nothing more needs to be done.