Lua is an imperative programming language first released in 1993 that is often embedded into other applications. The cross-platform Lua interpreter is available for most operating systems. Using the Lua API, programming languages with C interoperatibility interfaces can call Lua routines or be called from Lua.

For Fortran, several interface bindings exists that mostly focus on loading Lua-based configuration files:

Limited ISO C binding interface to Lua and library for using Lua scripts as configuration files in Fortran applications.
f2k3-lua (MIT)
Fortran 2003 interface to Lua for loading configuration files.
flook (MPL-2.0)
Abstraction layer for Lua-based configuration files.
FortLua (MIT)
Fork of AOTUS, mainly to read and write Lua configuration files.
fortran-lua53 (ISC)
Generic Lua 5.3 interfaces for Fortran 2003, for calling Lua from Fortran and vice versa.
luaf (MIT)
An incomplete set of Fortran 2003 bindings to Lua 5.1.

Lua provides a rich eco-system that may help to extend the scope of Fortran applications.


Lua can either be compiled from source or installed as a package. On FreeBSD, run:

# pkg install lang/lua53

On Linux, additional development headers may be required. Clone the GitHub repository and build the interface bindings fortran-lua53 with xmake:

$ git clone
$ cd fortran-lua53/
$ xmake

Or, run the Fortran Package Manager:

$ fpm build --profile=release

Alternatively, we may compile and archive the library manually:

$ gfortran12 -fPIC -c src/lua.f90
$ ar rcs libfortran-lua53.a lua.o

Link your Fortran application with libfortran-lua53.a and the Lua 5.3 library (statically or shared) .

Calling Lua from Fortran

Using the fortran-lua53 interface bindings, we can call arbitrary Lua routines. In the following basic example, a Fortran application will invoke the function hello() in hello.lua:

-- hello.lua
function hello()
   print("Hello, from Lua!")

In Fortran, we create a new Lua state, load the standard libraries, and execute the Lua function hello():

! example.f90
program main
    use, intrinsic :: iso_c_binding, only: c_ptr
    use :: lua
    implicit none
    type(c_ptr) :: l
    integer     :: rc

    l = lual_newstate()                 ! Get Lua state.
    call lual_openlibs(l)               ! Open standard libraries.

    rc = lual_dofile(l, 'hello.lua')    ! Load and execute Lua program from file.
    rc = lua_getglobal(l, 'hello')      ! Load function `hello()` onto stack.
    rc = lua_pcall(l, 0, 0, 0)          ! Call function from stack (0 arguments, 0 return values).

    call lua_close(l)
end program main

Link the program against Lua 5.3 and the static library libfortran-lua53.a:

$ gfortran12 -I/usr/local/include/lua53/ -L/usr/local/lib/lua/5.3/ \
  -o example example.f90 libfortran-lua53.a -llua-5.3

We may rely on pkg-config(1) to return the correct compiler and linker flags:

$ gfortran12 `pkg-config --cflags lua-5.3` -o example example.f90 \
  libfortran-lua53.a `pkg-config --libs lua-5.3`

The program outputs a greeting from Lua:

$ ./example
Hello, from Lua!

Calling Fortran from Lua

The interface bindings not only let us call Lua from Fortran but also Fortran from Lua. The Fortran procedures we want to access must be registered with lua_register() first.

In this particular example, only the subroutine hello() is exported that prints a friendly greeting to stdout. The function luaopen_fortran() will be called by Lua automatically to make the Fortran routines available. For real interoperability, the Lua stack pointer passed to the Fortran routine can be altered with the provided ISO C binding interfaces of fortran-lua53.

! fortran.f90
module fortran
    use, intrinsic :: iso_c_binding, only: c_int, c_funloc, c_ptr
    use :: lua
    implicit none

    public :: luaopen_fortran   ! Module registration function.
    public :: hello             ! Routine callable from Lua.
    function luaopen_fortran(l) bind(c)
        !! Utility function to register the Fortran routine `hello()`.
        type(c_ptr), intent(in), value :: l
        integer(kind=c_int)            :: luaopen_fortran

        call lua_register(l, &              ! Lua state.
                          'hello', &        ! Name of the Fortran routine.
                          c_funloc(hello))  ! Function pointer to the Fortran routine.
        luaopen_fortran = 1
    end function luaopen_fortran

    subroutine hello(l) bind(c)
        !! The Fortran routine callable from Lua.
        type(c_ptr), intent(in), value :: l

        print '(a)', 'Hello, from Fortran!'
    end subroutine hello
end module fortran

The Lua stack pointer has to be passed by value (attribute value for dummy argument l). The example Fortran module fortran.f90 and the static library libfortran-lua53.a will be linked into the shared library

$ gfortran12 -I/usr/local/include/lua53/ -L/usr/local/lib/lua/5.3/ \
  -shared -fPIC -o src/fortran.f90 lib/libfortran-lua53.a -llua-5.3

Linking with the help of pkg-config(1):

$ gfortran12 `pkg-config --cflags lua-5.3` -shared -fPIC -o \
  src/fortran.f90 lib/libfortran-lua53.a `pkg-config --libs lua-5.3`

The project workspace directory then contains:

Our Lua program hello.lua simply imports the shared library with the require() statement, then calls the Fortran subroutine hello():

-- hello.lua

Executing the Lua program outputs a greeting from Fortran:

$ lua53 ./hello.lua
Hello, from Fortran!

This approach is not platform-independent without recompiling the shared library for each targeted system.