Lua provides a perfect mechanism for managing typesafe handles that are held
exclusively by a Lua script to access a library programming interface. The
functions in the HPDF library are handle-based, but the handles created by the
library are held both by the script and the library. For example, the function
HPDF_Page_GetCurrentFont will return the font handle that is currently
registered in a page, even though the userdata that binds to this handle may
have fallen out of scope in the controlling Lua script. Furthermore, handles
can survive the document with which they were created and be reused in another
To address these aspects of the HPDF library, the Lua binding can simply use light userdata to hold the value of handles. In this case, type-safety can be achieved by means of a table in the C environment that maps the light userdata to integers or strings that identify their handle type. In this case, the type of all userdata that are passed to the binding are verified before passing the corresponding handle to the HPDF library. Every time a handle is created from the HPDF library, it is associated with its type in this table.
Alternatively, full userdata can be used to represent HPDF handles. This
approach allows the userdata to be associated with a metatable. The benefits of
this include the type-safety the metatable provides and the use of the
metamethod to support methods bound to the userdata. This simplifies the Lua
script by replacing a call like
The downside is that the userdata need to be preserved even after they fall out
of scope in the Lua script, because functions like
will need to return them. An ordinary table (not weak) in the C environment can
be used to map HPDF handles to full userdata, thus keeping the userdata from
The problem with both solutions is that a table in the C environment may
accumulate userdata (light in the first case and full in the second) that no
longer correspond to active handles. This is simply a garbage collection issue;
since the userdata stored in the environment can't be accessed from the Lua
script, they don't pose a programmatic risk other than consuming memory. Even
the memory waste is negligible in most cases; however, in the case where this
binding is used in long-running applications it could become an issue.
Consequently, an additional function that clears out this table is warranted.
It can be called by a long-running script at suitable points where all handles
are known to be closed. This could possibly be done when the function
HPDF_FreeDocAll is called and the specified document is the only one active.
The bulk of the LuaHPDF source file hpdf.c was automatically generated from the main header file of the Haru library, hpdf.h, using a Lua script. It uses light userdata to represent handles in the Haru library.