STM publishing: tools, technologies and change A WordPress site for STM Publishing

20Jan/11Off

Extending LuaTeX on Windows with plugins (DLLs)

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 called CLUAINPUTS, which tells Kpathsea where to search for files with extension .dll and .so (shared object file, on Linux). For example, in my hand-rolled texmf.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!