wxLua Documentation

wxLua is a Lua scripting language wrapper around the wxWidgets cross-platform GUI library. It consists of two IDE type editors that can edit and run Lua programs (wxLua and wxLuaEdit), an executable for running standalone wxLua scripts (wxLuaFreeze), a Lua module to load using require("wx") when using the standard Lua executable, and a library for extending C++ programs with a fast, small, fully embeddable scripting language.

Lua is a small scripting language written in ANSI C that can load and run interpreted scripts as either files or strings. The Lua language is fast, dynamic, and easy to learn. Lua contains a limited number of data types, mainly numbers, strings, functions, tables, and userdata. Perhaps the most powerful feature of the Lua language is that the tables can be used as either arrays or hash tables that can cross-reference numbers, strings, functions, and/or subtables.

wxLua adds to this small and elegant language the power of the C++ wxWidgets cross-platform GUI library. This includes the ability to create complex user interface dialogs, image manipulation, file manipulation, sockets, displaying HTML, and printing to name a few. You can use as much or as little of wxWidgets as you like and C++ developers can trim down the size by turning off preprocessor directives.

Additionally, wxLua adds a library for manipulating the bits of integer numbers using the Bitlib library from Reuben Thomas.

References:

wxLua website : http://wxlua.sourceforge.net
wxLua Sourceforge page : http://sourceforge.net/projects/wxlua
Lua website : http://www.lua.org
wxWidgets website : http://www.wxwidgets.org
Bitlib library : http://rrt.sc3d.org/Software/Lua/
User and developer mailing list : wxlua-users@lists.sourceforge.net

Contents

  1. Version Information
  2. Requirements
  3. Introduction to Lua (very brief)
  4. Bit Library
  5. Programming in wxLua
  6. wxLua Samples and How to Run Them
    1. How to Run the Samples
    2. Provided Samples
  7. wxLua Applications
    1. wxLua
    2. wxLuaFreeze
    3. wxLuaEdit
  8. wxLua Utils
    1. bin2c.lua
    2. wrapmodule.wx.lua
  9. wxLua Sourcecode Modules
  10. wxLua C++ Programming Guide
    1. Data stored in Lua's LUA_REGISTRYINDEX table
    2. Functions to Create a wxLuaState
    3. Using a wxLuaState

Version Information

Requirements

An end user of wxLua can use the binary packages of wxLua and everything that's needed is contained within it. C++ programmers or users on platforms that we don't provide binaries will need a development library of wxWidgets, typically the source code itself that you have compiled on your system. More information about compiling wxLua is contained in the install.htm file and on http://wxlua.sourceforge.net.

Introduction to Lua (very brief)

Assuming that you have a cursory understanding of programming techniques, this primer should give you a good enough feel for Lua to understand the sample programs and begin to write your own. You should in any case read the documentation at www.lua.org.
do
-- create a new local scope
local a = 2
end
local a, b, c = 1, 2, 3 -- can assign multiple values
a = 1; b = 2; c = 3 -- use ; for multiple lines of code on single line
a, b, c = 1, 2, 3 -- this works too
if (a == 1) and ((b <= 2) or (c ~= 3)) then
print(a+b/c)
elseif a == 2 then -- no parentheses necessary
print(a)
else
print(b)
end
function CheckA(val) if val == 5 then return true end end -- returns nil if val ~= 5
local a = 1
while a < 10 do
print(a)
a = a + 1 -- no increment operator
if CheckA(a) then break end
end
local a = 1
while a < 10 do while true do
a = a + 1 -- no increment operator
if CheckA(a) then
break
else
print(a)
end
break end end
local a = 1
repeat
local temp = a * 2
print(temp, type(temp))
a = a + 1 -- no increment operator
until a > 10
local a = "hello"
for a = 1, 10 --[[, increment]] do -- optional increment value, else 1
local temp = a * 2
print(temp)
end
print(a) -- a == "hello" since loop counter variable is local to the loop
function DoStuff(a, b, c)
a = b*c -- does not change global and/or input number a
local function Calc(a)
return a*2
end

return Calc(a)*b*c -- or for multiple values "return a*b*c, a*b"
end
-- call function
a = 10
result = DoStuff(a, 1, 2)
-- can also put function into a table
stuff = {}
stuff.DoStuff = DoStuff
result = stuff.DoStuff(1, 2, 3)
print(a, result) -- "10, 72" since a is not changed

Bit Library

wxLua automatically loads a library for manipulating the bits of an integer and puts it into the global "bit" table. This is because wxWidgets often uses enumeration flags to control the behavior of functions and for compactly storing status information. You can easily "or" bits by adding them together and this is the preferred method, for example 0x02 + 0x04 = 0x06 or bitwise 0110. If the bits you're trying to "or" are not unique (perhaps one is a bit mask) this fails, 0x01 + 0x03 = 0x04 or bitwise 0100 (oops).

wxLua uses the bitlib library written by Reuben Thomas and since the code for it is very small, it's embedded into the wxLua sourcecode.

All function arguments should be integers. The number of bits available for logical operations depends on the data type used to represent Lua numbers; this is typically 8-byte IEEE floats, which give 53 bits (the size of the mantissa).
The logical operations start with "b" for "bit" to avoid clashing with reserved words; although "xor" isn't a reserved word, it seemed better to use "bxor" for consistency.

Programming in wxLua

Programming in wxLua means that you're writing Lua programs using the Lua language using an additional table of functions, objects, numbers, strings, and "classes" in the namespace wx from wxWidgets. Additional libraries may be added as bindings and can be placed in their own "namespace" table, but for the examples below we will use the wx table.

The list below are the tables that wxLua creates containing the binding functions or objects. These are in addition to the standard Lua tables; coroutine, debug, io, math, os, package, string, table. Note that the wxaui and wxstc libraries have been separated into their own tables since they are fairly specialized libraries.
The semantics for accessing wxWidgets elements in wxLua tries to map as closely as possible to the underlying C++ notation so that the official C++ documentation may be used as a reference, http://www.wxwidgets.org/docs. The most common case where wxLua deviates from C++ is when values are passed by reference to a function to be changed; wxLua will return multiple values instead. Please see the wxluaref.html document that lists all the wxWidgets objects wrapped by wxLua and take note of the functions that are marked %override since you will need to use them as described in that document. You should also look at the binding.html file, even if you do not plan to write your own bindings, to get a better understanding of the wxluaref.html file.

Strings: wxLua does not typically use the wxString class for strings, rather it uses Lua strings. This means that all wxWidgets functions that take a wxString parameter take either a wxString userdata or (preferred) a Lua string (Lua variables that are of type(var) == "string"). Functions that return wxStrings convert the value into a Lua string for convenience. The conversion from the Lua ANSI C 8-bit char* string to a wxString (which may be a Unicode wchar* string) is done internally.

wxArrayString and wxSortedArrayString: Function parameters that take a "const wxArrayString& arr" or "wxArrayString arr" will accept either a wxArrayString userdata or a Lua table that has numeric indexes and string values and convert it into a wxArrayString for the function call. If the function call is "wxArrayString& arr" or "wxArrayString* arr" you must provide a wxArrayString userdata since the C++ function will most likely modify the wxArrayString that's passed to it.

wxArrayInt: Function parameters that take a "const wxArrayInt& arr" or "wxArrayInt arr" will accept either a wxArrayInt userdata or a Lua table that has numeric indexes and numeric values and convert it into a wxArrayInt for the function call. If the function call is "wxArrayInt& arr" or "wxArrayInt* arr" you must provide a wxArrayInt userdata since the C++ function will most likely modify the wxArrayInt that's passed to it.

Location of the wxWidgets objects declared in a C++ header files in the wx Lua table

wxLua Samples and How to Run Them

There are a number of sample programs in the wxLua/samples directory. These programs demonstrate how to write simple programs and try to show how to use some of the many classes of wxWidgets. They are a good resource to learn how to write your own more complicated programs.

We welcome any enhancements or additional samples that might be generally useful to the wxLua community. Please understand that any code you contribute has to be maintained and easily understood so try to keep things simple and clear.

If something in wxLua seems to not work as expected it is best to try to duplicate your error in the simplest possible way in one of the samples and ask on the wxlua-users@lists.sourceforge.net mailing list.

Why are the samples named sample.wx.lua? To allow them to be colorized correctly in syntax highlighting editors, yet denote to people that they are for wxLua and must be run using a wxLua executable or the wxLua module.

How to Run the Samples

The examples below are for MS Windows .exe executables, but the same applies for Linux or OSX, just remove the .exe extension for the executable. See also wxLua Applications for more information about these programs.

Provided Samples

wxLua Applications

The applications that wxLua provides are in the wxLua/apps directory. These are C++ programs that are compiled against the wxWidgets library and the wxWidgets wxStyledTextCtrl library.

wxLua Utils

Utility programs for wxLua are located in the wxLua/util directory.

wxLua Sourcecode Modules

wxLua is broken up into "modules" that are compiled into libraries so that you can choose to link to some or all of them. The directory structure of the modules dir is such that in your program you need only add the include path to wxLua/modules in your compiler settings and then in the code always write #include "modulename/include/filename.h".

wxLua C++ Programming Guide

The documentation for the wxLua library is in the header files and descriptions are given for each function, enum, etc. Please read through them to get a feel for what functions wxLua provides. Below is a brief synopsis of wxLua for C++ programmers.

Lua uses char strings while wxWidgets uses the wxString class which uses the wxChar data type. Depending on whether you have compiled wxWidgets in Unicode mode or not, wxChar can be either wchar or char. Therefore, wxLua uses the functions "wxString lua2wx(const char* str)" and "const wxCharBuffer wx2lua(const wxString& str)" to translate between the two. Note that wxCharBuffer can be used as a const char* string directly without any casting.

The core of wxLua is based upon a ref counted wxLuaState class derived from the wxWidget's wxObject class. The wxLuaState class contains as a member of it's ref data the 'C' lua_State struct which is the heart of Lua. Since the class is ref counted, it should be passed as const wxLuaState& and can be used in much the same way as a wxBitmap, wxPen, or any of the other wxObject derived classes that make use of it's ref counting mechanism. What this means for wxLua is that instead of keeping pointers to the lua_State you have instances of the wxLuaState, there is a slight overhead for this, but it is minimal. When the lua_State is closed, all the wxLuaStates sharing the ref data can check their ref data to see if the lua_State is NULL and segfaults from dangling pointers are avoided. The reason why this is a good idea is that wxWidgets has delayed wxWindow deletion and things can get out of order. Care must be taken for pushed event handlers from Lua because if the lua_State is closed, but the window hasn't been deleted just yet... It's best to have a way to check and the wxLuaState wraps this all up.

When the wxLuaState is Ok() the wxLuaState has it's ref data and the lua_State is created. If it's not Ok() then most wxLuaState functions will assert in debug mode, so it's always best to compile in debug mode until you're sure things are working properly.

The wxLuaState contains all of the Lua 'C' functions, such as lua_gettop(lua_State* L), but as member functions named lua_GetTop() which use the internal lua_State and check for it's validity before use. The functions are capitalized to make them easier to find in an editor. If you want the greatest performance just use wxLuaState::GetLuaState() and directly manipulate the returned pointer to the lua_State.

It is instructive to follow the creation of the wxLuaState by looking at bool wxLuaState::Create(wxEvtHandler *handler, wxWindowID id) in wxLua/modules/wxlua/src/wxlstate.cpp.
  1. The lua_State is created using lua_open() and then the standard Lua libraries are loaded, base, table, string, math, and so on using luaL_openlibs(L) as well as luaopen_bit(L) to open the bit library we use.
  2. The function wxLuaState::Create(L, wxLUASTATE_USESTATE) is called to finish setting up the lua_State.
    1. The wxObject::m_refData is created as a new wxLuaStateRefData(). This ref data class contains a pointer to the lua_State struct and to a shared wxLuaStateData class that is also created. If a Lua program running in this wxLuaState creates coroutines, each will have their own wxLuaStateRefData and associated lua_State, but they will all share the same wxLuaStateData class.
    2. The C lua_State is added to a hash table to allow looking up the owner wxLuaStateRefData when Lua calls the C wxLua binding functions with the lua_State as the only parameter. A new wxLuaState with the wxLuaStateRefData set using wxObject::SetRefData(), which does not "ref" the data, but simply sets it, is used since we do not want an extra "ref". The same wxLuaState is pushed into the LUA_REGISTRYINDEX table as a lightuserdata using the &wxlua_lreg_wxluastate_key as a secondary means to find the wxLuaState "owner" of the lua_State which will be used for coroutines since there is no way to determine when a coroutine (new lua_State) is created and then destroyed.
    3. The tables and values that wxLua uses to store information about the bindings or track it's state are pushed into the LUA_REGISTYINDEX. Information about these items can be found in the next section.
    4. We register a print() function for Lua to get the output of Lua print() statements to send messages as wxLuaEvents, see wxEVT_LUA_PRINT.
  3. The bindings are registered by calling wxLuaState::RegisterBindings().
    1. Each binding has wxLuaBinding::RegisterBinding(...) called for it.
  4. At the end of creation a wxLuaEvent is sent with the wxEVT_LUA_CREATION event type.

Data stored in Lua's LUA_REGISTRYINDEX table

Below are the list of indexes in the LUA_REGISTRYINDEX table that the wxLuaState creates and uses. The keys are const char* strings with its address pushed as a light userdata because a pushing the string itself requires that it be hashed and it was found to take a considerable amount of the total time of a function call.

// ----------------------------------------------------------------------------
// Special keys used by wxLua in the LUA_REGISTRYINDEX table.
//
// Note: We do not push a human readable string for these because Lua always
// makes a copy and hashes the string, this takes a considerable amount of
// time when benchmarked using valgrind.
// ----------------------------------------------------------------------------

// Light userdata used as keys in the Lua LUA_REGISTRYINDEX table for wxLua.
// Note that even though these keys have values, they're not used, just the memory address.

// The key in the LUA_REGISTRYINDEX table that is a numerically keyed table indexed
// on the wxLua types where each item is a userdata metatable for a C++ class.
// Note: The wxLua types WXLUA_TXXX that correspond to the Lua LUA_TXXX types
// are not stored in this table since they do not use our metatables.
// The keys in this table are all > 1. They values are either tables or 0
// if the wxLuaBinding containing the wxLua type was not registered.
// LUA_REGISTRYINDEX[&wxlua_lreg_types_key][wxLua type number] = { metatable for a C++ class }
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_types_key;
// The key in the LUA_REGISTRYINDEX table that is a numerically keyed table
// with references to Lua objects we want to keep a handle to. The object could be
// anything, a table, function, number, string, userdata...
// LUA_REGISTRYINDEX[&wxlua_lreg_refs_key][ref number] = Lua object
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_refs_key;
// The key in the LUA_REGISTRYINDEX table that is a numerically keyed table
// with references to objects the wxLuaDebugData wants to keep a handle to by
// storing their value for lookup. It is used only for the wxLuaDebugData.
// LUA_REGISTRYINDEX[&wxlua_lreg_debug_refs_key][ref number] = Lua object
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_debug_refs_key;
// The key that in the LUA_REGISTRYINDEX table that is a lookup table of string
// C++ classname keys and lightuserdata pointers to the associated wxLuaBindClass struct.
// LUA_REGISTRYINDEX[&wxlua_lreg_debug_refs_key][wxLuaBindClass.name] = lightuserdata(&wxLuaBindClass)
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_classes_key;
// The key in the LUA_REGISTRYINDEX table that is a table
// of Lua objects/functions assigned to wxLua userdata programatically in Lua.
// LUA_REGISTRYINDEX[&wxlua_lreg_derivedmethods_key][lightuserdata(obj_ptr)] =
// {["derived func/value name"] = wxLuaObject(Lua function/value), ...}
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_derivedmethods_key;
// The key in the LUA_REGISTRYINDEX table who's value is a lightuserdata
// of the wxLuaState for this lua_State.
// LUA_REGISTRYINDEX[&wxlua_lreg_wxluastate_key] = lightuserdata(&wxLuaState)
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_wxluastate_key;
// The key in the LUA_REGISTRYINDEX table that is a table of lightuserdata
// wxLuaBindings and the ref to the Lua table they were installed into.
// LUA_REGISTRYINDEX[&wxlua_lreg_wxluabindings_key] = {lightuserdata(&wxLuaBinding) = wxlua_lreg_refs_key ref#, ...}
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_wxluabindings_key;
// The key in the LUA_REGISTRYINDEX table that is a table of all
// objects that we've pushed into Lua using wxluaT_pushuserdatatype().
// Note: A single object like a wxWindow may be pushed with multiple wxLua types.
// e.g. wxWindow* w = wx.wxWindow() retrieve the window later from wxObject* wxEvent:GetEventObject()
// LUA_REGISTRYINDEX[&wxlua_lreg_weakobjects_key][lightuserdata(obj_ptr)] =
// { wxLua type1 = weak fulluserdata, wxLua type2 = weak fulluserdata... }
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_weakobjects_key;
// The key in the LUA_REGISTRYINDEX table that is a table of all
// objects to delete that were added using wxluaO_addgcobject().
// Note that non wxObject classes use wxLUA_DECLARE_ENCAPSULATION so
// the key is the object pointer and the value is the wxObject encapsulation.
// Both the key and the value are the same if not encapsulated.
// LUA_REGISTRYINDEX[&wxlua_lreg_gcobjects_key][lightuserdata(obj_ptr)] =
// lightuserdata(wxObject derived class)
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_gcobjects_key;
// The key in the LUA_REGISTRYINDEX table that is a table of all
// wxLuaEventCallbacks that we've created.
// LUA_REGISTRYINDEX[&wxlua_lreg_evtcallbacks_key][lightuserdata(&wxLuaEventCallback)] =
// lightuserdata(&wxEvtHandler)
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_evtcallbacks_key;
// The key in the LUA_REGISTRYINDEX table that is a table of wxWindow keys and
// wxLuaWinDestroyCallback values that we've created.
// LUA_REGISTRYINDEX[&wxlua_lreg_windestroycallbacks_key][lightuserdata(&wxWindow)] =
// lightuserdata(wxLuaWinDestroyCallback)
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_windestroycallbacks_key;
// The key in the LUA_REGISTRYINDEX table that is a table of all
// top level wxWindows that we've created and need to destroy when closed.
// LUA_REGISTRYINDEX[&wxlua_lreg_topwindows_key][lightuserdata(&wxWindow)] = 1
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_topwindows_key;
// The key in the LUA_REGISTRYINDEX table that has a boolean value
// of whether the Lua code has prepended a '_' to function name to indicate
// that they want the base class function called.
// LUA_REGISTRYINDEX[&wxlua_lreg_callbaseclassfunc_key] = true/false
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_callbaseclassfunc_key;
// The key in the LUA_REGISTRYINDEX table that has a wxEventType (integer) value
// of the current wxEvent is that is being run or wxEVT_NULL if not in an event.
// LUA_REGISTRYINDEX[&wxlua_lreg_wxeventtype_key] = wxEventType (wxEVT_NULL)
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_wxeventtype_key;
// The key in the LUA_REGISTRYINDEX table that has a wxLuaStateData class
// lightuserdata value for the wxLuaState.
// LUA_REGISTRYINDEX[&wxlua_lreg_wxluastatedata_key] = lightuserdata(&wxLuaStateData)
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_wxluastatedata_key;
// The key in the LUA_REGISTRYINDEX table that is a weak keyed table of
// the tables wxLua pushed into the registry with their keys as values.
// This is used by the wxLuaDebugData to know if the table is one of the wxLua
// registry tables for better wxLuaStackDialog performance.
// LUA_REGISTRYINDEX[&wxlua_lreg_regtable_key][weak {wxlua_lreg_XXX_key table}] =
// lightuserdata(&wxlua_lreg_XXX_key)
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_lreg_regtable_key;

// Light userdata used as keys in the metatables created for the class userdata objects.
// Note that even though these keys have values, they're not used, just the memory address.

// wxLua userdata metatable structure:
// {
// lightuserdata(&wxlua_metatable_type_key) = wxLua type number in wxlua_lreg_types_key table
// lightuserdata(&wxlua_metatable_wxluabindclass_key) = lightuserdata(&wxLuaBindClass)
// __gc = function(wxlua_wxLuaBindClass__gc)
// __index = function(wxlua_wxLuaBindClass__index)
// __newindex = function(wxlua_wxLuaBindClass__newindex)
// __tostring = function(wxlua_wxLuaBindClass__tostring)
// }

// The key of a metatable used for wxLua userdata that is the wxLua type number in the
// wxlua_lreg_types_key table this metatable is for.
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_metatable_type_key;
// The key of a metatable used for wxLua userdata that stores a lightuserdata
// of the wxLuaBindClass struct for this class.
extern WXDLLIMPEXP_DATA_WXLUA(const char*) wxlua_metatable_wxluabindclass_key;

Functions to Create a wxLuaState

Using a wxLuaState