IupLua Advanced Guide
Exchanging "Ihandle*" between C and Lua
Each binding to a version of Lua uses different features of the language in order to implement IUP handles (Ihandle) in Lua. Therefore, functions have been created to help exchange references between Lua and C.
In C, to push an Ihandle in Lua's stack, use the function:
iuplua_pushihandle(Ihandle *ih); // for Lua3 iuplua_pushihandle(lua_State *L, Ihandle *ih); // for Lua5
In C, to receive an Ihandle in a C function called from Lua, just use one of the following code:
Ihandle* ih = (Ihandle*)lua_getuserdata(object); // for Lua 3 Ihandle* ih = *(Ihandle**)lua_touserdata(L, pos); // for Lua 5
or using parameter checking:
Ihandle* iuplua_checkihandle(int pos); // for Lua 3 Ihandle* iuplua_checkihandle(lua_State *L, int pos); // for Lua 5
In Lua, if the handle is a user data create with the above structure, but not mapped to a Lua object, use the function:
iup.RegisterHandle(handle, typename)
where "typename" is the string returned in IupGetType(handle)
In Lua, to access a handle created in C as a Lua object, alternatively use the function:
handle = iup.GetFromC(name)
where "name" is the name of the element previously defined with IupSetHandle.
Error Handling
In Lua 3 the _ALERT function is redefined to show the message in a dialog.
In Lua 5 there is no such function, so to improve the error report the following functions have been created to execute Lua code:
int iuplua_dofile(lua_State *L, char *filename); int iuplua_dostring(lua_State *L, const char *string, const char *chunk_name);
These functions mimics the implementation in the standalone interpreter for Lua 5, that displays the error message followed by the stack.
If the these functions are used the errors will be reported through the "iup._ERRORMESSAGE(msg)" function. By default _ERRORMESSAGE is defined to show a dialog with the error message.
When printing an Ihandle reference the returned string is "IUP(type): address", for example "IUP(dialog): 08C55240".
The Architecture Behind IupLua 3
The Lua API for the IUP system was based on object classes representing the different interface elements. A hierarchy was built among these classes, with the main purpose of reusing code. Code inheritance was implemented precisely as described in the Lua 3 user guide.
The root of this hierarchy is the WIDGET class. It contains the basic procedures for construction, parameter type verification, and allocation of structures for controlling IUP’s interface elements. This class also defines the basic parameters of all classes, such as handle (which stores the handle of the associated IUP element) and parent (used to implement the inheritance mechanism).
Even though almost all classes directly descend from the WIDGET class, some other classes serve as mediators in the tree. This is the case of the COMPOSITION class, located among the composition element classes: IUPHBOX, IUPVBOX and IUPZBOX.
Some classes use part of the code from other classes, when they are very similar. This happens to IUPITEM and IUPTOGGLE, which reuse the code related to the verification of parameter types and to the definition of the action callback in the IUPBUTTON class. Class IUPMULTILINE inherits several characteristics from IUPTEXT, such as the definition of the action callback and the verification of parameter types.
The complete class hierarchy for the standard controls can be represented as follows:
WIDGET IUPBUTTON IUPITEM IUPTOGGLE IUPCANVAS COMPOSITION IUPHBOX IUPVBOX IUPZBOX IUPDIALOG IUPFILL IUPFRAME IUPIMAGE IUPLABEL IUPLIST IUPMENU IUPRADIO IUPSEPARATOR IUPSUBMENU IUPTEXT IUPMULTILINE
The Architecture Behind IupLua 5
There are two important names in IupLua5: "iup handle" and "iup widget".
When you create an IUP element in Lua 5 it is created a table with a metatable called "iup widget". This metatable has its "__index" method redefined so when an index is not defined it looks for it in the "parent" table. The table it self represents the class of the control. And all the classes inherit the implementation of the base class WIDGET. Each control class must implement the "createElement" method of the class. The WIDGET class also a member called "handle" that contains the Ihandle* in Lua. The constructor of the WIDGET class returns the handle.
The Ihandle* is represented in Lua as a table with a metatable called "iup handle". This metable has its "__index", "__newindex" and "__eq" methods redefined. The index methods are used to implement the set and get attribute facility. The handle knows its class because it is stored in its "parent" member.
Since the controls creation is done by the "iup.<control>" function, the application does not use the WIDGET class directly. All the time the application only uses the handle.
So for example the IupLabel:
iup.label calls iup.LABEL:constructor since iup.LABEL.parent = iup.WIDGET and iup.LABEL:constructor is not implemented it calls iup.WIDGET:constructor then iup.WIDGET:constructor calls iup.LABEL:createElement and finally returns the created handle
The complete class hierarchy for the standard controls can be represented as follows:
WIDGET BUTTON ITEM TOGGLE CANVAS BOX HBOX VBOX ZBOX MENU DIALOG FILL FRAME IMAGE LABEL LIST RADIO SEPARATOR SUBMENU TEXT MULTILINE