Lua
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:
- AOTUS
- Limited ISO C binding interface to Lua and library for using Lua scripts as configuration files in Fortran applications (MIT).
- f2k3-lua
- Fortran 2003 interface to Lua for loading configuration files (MIT).
- flook
- Abstraction layer for Lua-based configuration files (MPL-2.0).
- FortLua
- Fork of AOTUS, mainly to read and write Lua configuration files (MIT).
- fortran-lua53
- Generic Lua 5.3 interfaces for Fortran 2008, for calling Lua from Fortran and vice versa (ISC).
- fortran-lua54
- Lua 5.4 interfaces for Fortran 2008 (ISC).
- luaf
- An incomplete set of Fortran 2003 bindings to Lua 5.1 (MIT).
Lua provides a rich eco-system that may help to extend the scope of Fortran projects.
fortran-lua54
Lua can either be compiled from source or installed as a package. On FreeBSD, run:
# pkg install lang/lua54
On Linux, additional development headers may be required. Clone the GitHub repository and build the interface bindings fortran-lua54 with xmake:
$ git clone https://github.com/interkosmos/fortran-lua54
$ cd fortran-lua54/
$ xmake
Or, run the Fortran Package Manager:
$ fpm build --profile release
Alternatively, we may compile and archive the library manually:
$ gfortran13 -fPIC -c src/lua.f90
$ ar rcs libfortran-lua54.a lua.o
Link your Fortran application with libfortran-lua54.a
and the
Lua 5.4 library (statically or shared) .
Calling Lua from Fortran
Using the fortran-lua54 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!")
end
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
use :: lua
implicit none
type(c_ptr) :: l ! Lua pointer.
integer :: rc ! Return code.
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.4 and the static library
libfortran-lua54.a
:
$ gfortran13 -I/usr/local/include/lua54 -L/usr/local/lib/lua/5.4 -o example \
example.f90 libfortran-lua54.a -llua-5.4
The include and library search paths may differ on Linux. Alternatively, we can run pkg-config(1) to return the correct compiler and linker flags:
$ gfortran13 `pkg-config --cflags lua-5.4` -o example example.f90 libfortran-lua54.a \
`pkg-config --libs lua-5.4`
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
registered Fortran function available. The postfix fortran
in the
function name must match the name of the shared library. If the name of the
library would be, for instance, libfortran.so
, the function must
be named luaopen_libfortran()
instead.
! 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.
contains
function luaopen_fortran(l) bind(c) result(n)
!! Utility function to register the Fortran routine `hello()`.
type(c_ptr), intent(in), value :: l !! Lua pointer.
integer(kind=c_int) :: n !! Always 1.
call lua_register(l, & ! Lua pointer.
'hello', & ! Name of the Fortran routine.
c_funloc(hello)) ! Function pointer to the Fortran routine.
n = 1
end function luaopen_fortran
function hello(l) bind(c) result(n)
!! The Fortran routine callable from Lua.
type(c_ptr), intent(in), value :: l !! Lua pointer.
integer(kind=c_int) :: n !! Number of results.
print '(a)', 'Hello, from Fortran!'
n = 0
end function hello
end module fortran
The Lua stack pointer l
has to be passed by value. The example
Fortran module fortran.f90
and the static library
libfortran-lua54.a
will be linked into the shared library
fortran.so
:
$ gfortran13 -I./include -I/usr/local/include/lua54 -L/usr/local/lib/lua/5.4 -fPIC -shared \
-o fortran.so src/fortran.f90 lib/libfortran-lua54.a -llua-5.4
Linking with the help of pkg-config(1):
$ gfortran13 -I./include `pkg-config --cflags lua-5.4` -fPIC -shared \
-o fortran.so src/fortran.f90 lib/libfortran-lua54.a `pkg-config --libs lua-5.4`
The project workspace directory then contains:
<project>/
include/
lua.mod
lib/
libfortran-lua54.a
src/
fortran.f90
hello.lua
fortran.so
The Lua script hello.lua
has to import the shared library
fortran.so
with the require()
statement first, and
then calls the registered Fortran function hello()
:
-- hello.lua
require("fortran")
hello()
The library must be located in the Lua search path. Executing the script outputs a greeting from Fortran:
$ lua54 ./hello.lua
Hello, from Fortran!
This approach is not platform-independent without recompiling the shared
library fortran.so
for each targeted system.
References
< SQLite | [Index] | Tcl/Tk > |