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 (MIT)
- 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.
fortran-lua53
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 https://github.com/interkosmos/fortran-lua53
$ 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!")
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, 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.
contains
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 fortran.so
:
$ gfortran12 -I/usr/local/include/lua53/ -L/usr/local/lib/lua/5.3/ \
-shared -fPIC -o fortran.so 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 fortran.so \
src/fortran.f90 lib/libfortran-lua53.a `pkg-config --libs lua-5.3`
The project workspace directory then contains:
project/
src/
fortran.f90
lib/
libfortran-lua53.a
hello.lua
fortran.so
Our Lua program hello.lua
simply imports the shared library
fortran.so
with the require()
statement, then calls
the Fortran subroutine hello()
:
-- hello.lua
require("fortran")
hello()
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 fortran.so
for each targeted system.
References
< SQLite | [Index] | Tcl/Tk > |