About 6 months ago I came across an article and presentation by Luigi Scarso called “LuaTEX lunatic”, with a subtitle And Now for Something Completely Different. And different it was because, for me, it opened my eyes to some of the real power of LuaTeX: extending it via C/C++ libraries. Luigi’s truly excellent paper is Linux-centric but the general ideas hold true for any platform, including Windows.
The power of Lua’s require(...)
function
The Lua language provides a function called require(...)
which allows you to load and run libraries – that can be written in pure Lua or the Lua C API. Refer to the Libraries And Bindings page on lua-users.org for more details.
Using
require(...)
with LuaTeX: a primer
Once again, the secret ingredient is the LuaTeX command\directlua{...}
which, as discussed in previous posts, lets you run Lua code from within documents you process with LuaTeX. Suppose you have a DLL which you, or someone else, have written with a Lua binding and you want to use it with LuaTeX. How do you do it?Firstly, within
texmf.cnf
you need to define a variable calledCLUAINPUTS
, which tells Kpathsea where to search for files with extension .dll and .so (shared object file, on Linux). For example, in my hand-rolledtexmf.cnf
the setting is
CLUAINPUTS=$TEXMF/dlls
The LuaTeX Reference Manual notes the default setting of
CLUAINPUTS=.:$SELFAUTOLOC/lib/{$progname,$engine,}/lua//
World’s most pointless DLL code?
Just for completeness, and by way of an ultra-minimal example, here is probably the world’s most pointless C code for a DLL that you can call from LuaTeX. To compile this you will, of course, need to ensure that you link to the Lua libraries (note that I use Microsoft’s Visual Studio for this)
#include ‹windows.h›
#include "lauxlib.h"
#include "lua.h"
#define LUA_LIB int __declspec(dllexport)
static int helloluatex_greetings(lua_State *L){
printf("Hello to LuaTeX from the world's smallest DLL!");
return 0;
}
static const luaL_reg helloluatex[] = {
{"greetings", helloluatex_greetings},
{NULL, NULL}
};
LUA_LIB luaopen_helloluatex (lua_State *L) {
luaL_register(L, "helloluatex", helloluatex);
return 1;
}
You need to compile the above C code into a DLL called helloluatex.dll
and copy it to the directory or path pointed to by CLUAINPUTS
.
LuaTeX code to use our new DLL
Here is a minimal (LaTeX) file to load helloluatex.dll
and call the greetings
function we defined via the Lua C API. We'll call the file dlltest.tex
.
\documentclass[11pt,twoside]{article}
\begin{document}
\pagestyle{empty}
\directlua{
require("helloluatex")
helloluatex.greetings()
}
\end{document}
Running this as luatex --fmt=lualatex dlltest.tex
gives the output
This is LuaTeX, Version beta-0.65.0-2010122301
(c:/.../dlltest.tex
LaTeX2e <2009/09/24>
(c:/.../formats/pdflatex/base/article.cls
Document Class: article 2007/10/19 v1.4h Standard LaTeX document class
(c:/.../formats/pdflatex/base/size11.clo))
No file dlltest.aux.
Hello to LuaTeX from the world's smallest DLL!(./dlltest.aux) )
262 words of node memory still in use:
2 hlist, 1 vlist, 1 rule, 2 glue, 39 glue_spec, 2 write nodes
avail lists: 2:12,3:1,6:3,7:1,9:1
No pages of output.
Transcript written on dlltest.log.
Note that you see Hello to LuaTeX from the world's smallest DLL!
printed out to the DOS window.
This is, of course, a rather simple example so I'll try to provide more useful examples over the coming weeks and months. I have integrated a number of libraries into LuaTeX, including FreeType and GhostScript, and many others, so I'll try to cover some of these wonderful C libraries as time permits. Stay tuned!
Pingback: Adding a UTF-8-capable regular expression library to LuaTeX « STM publishing: tools, technologies and change