wxLua 2.8.12 - Manual

wxLua is a Lua scripting language wrapper around the wxWidgets cross-platform C++ GUI library. It consists of two IDE type editors that can edit, debug, and run Lua programs (wxLua and wxLuaEdit), an executable for running standalone wxLua scripts (wxLuaFreeze), a Lua module that may be loaded 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, booleans, strings, functions, tables, and userdata. Perhaps the most powerful feature of the Lua language is that tables can be used as either numerically indexed arrays or associative arrays that can cross-reference any variable type to any other variable type.

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, file and image manipulation, drawing, 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 the bindings 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/
Mailing list - wxlua-users@lists.sourceforge.net

Table of Contents

  1. 1 - Version Information
  2. 2 - Requirements
  3. 3 - Brief Introduction to Lua
  4. 4 - Bit Library
  5. 5 - Programming in wxLua
    1. 5.1 - Naming, location, and usage of the wxWidgets objects declared in the C++ header files in the wx Lua table
  6. 6 - wxLua Samples and How to Run Them
    1. 6.1 - How to Run the Samples
    2. 6.2 - Provided Samples
  7. 7 - wxLua Applications
    1. 7.1 - wxLua
    2. 7.2 - wxLuaEdit
    3. 7.3 - wxLuaFreeze
    4. 7.4 - Lua Module using require()
  8. 8 - wxLua Utils
    1. 8.1 - bin2c.lua
  9. 9 - wxLua Sourcecode Modules
  10. 10 - wxLua C++ Programming Guide
    1. 10.1 - Data stored in Lua's LUA_REGISTRYINDEX table
    2. 10.2 - Functions to Create a wxLuaState
    3. 10.3 - Using a wxLuaState

1 - Version Information

2 - 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 for will need a development library of wxWidgets; typically the source code that you have compiled on your system. More information about compiling wxLua is contained in the install.html file and on http://wxlua.sourceforge.net.

3 - Brief Introduction to Lua

This short primer is meant to give you a good enough feel for Lua that you will be able to understand the sample programs and begin to write your own. It assumes that you have a cursory understanding of general programming techniques. 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
case = {}
case[1] = function() print("Hello #1") end -- anonymous function
case[2] = function() print("Hello #2") end
...
if case[value] then
    case[value]()
else
    print("Unknown case value")
end
function Check5(val) -- returns nil if val ~= 5
    if val == 5 then
        return true
    end
end

local a = 1
while a < 10 do
    print(a)
    if Check5(a) then break end
    a = a + 1 -- no increment operator
end
local a = 0
while a < 10 do while true do
    a = a + 1 -- no increment operator
    if Check5 (a) then
        break -- break in the inner while loop to "continue" in the outer loop
    else
        print(a)
    end

    break end -- break out of inner while loop
end
local a = 10
repeat
    local temp = a * 2
    print(temp, type(temp))
    a = a - 1 -- no decrement operator
until a < 0
local a = "hello"
for a = 1, 10 --[[, increment]] do -- optional increment value, default increment is 1
    local temp = a * 2
    print(temp)
end

print(a) -- a == "hello" since loop counter variable is local to the loop
-- Print the keys in table t that have the values of in the table values
function PrintKeys(t, values, cmp_case)
    -- use nested functions for repetitive code or to simplify code
    local function cmp_values(a, b)
        if cmp_case then -- can use upvalue variables
            return a == b
        else
            return string.lower(a) == string.lower(b)
        end
    end
    local function find_key(t, val)
        for k,v in pairs(t) do
            if cmp_values(val, v) then return k end
        end
    end
    for i = 1, #vals do
        print(find_key(t, values[i]), values[i])
    end
end

-- prints "a1 a2", "b1 b2", "nil C2"
PrintKeys({a1 = "a2", b1 = "b2", c1 = "c2"}, {"a2", "b2", "C2"}, true)

-- Varargs example; prints "4 4 4 20 20" and "table: 0183B820 10 30 5"
function Varargs(...)
    local args = {...}
    print(select("#", ...), #{...}, #args, args[2], unpack({...}, 2, 2))
    return args, unpack(args) -- same as return ...
end

vals, val1, _, val3 = Varargs(10, 20, 30, 40)
print(vals, val1, val3, select("#", Varargs(10, 20, 30, 40)))

4 - 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 powers of 2 (perhaps one is a bit mask) this fails, 0x01 + 0x03 = 0x04 or bitwise 0100 (oops) instead of the desired 0011.

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.

5 - Programming in wxLua

Programming in wxLua means that you're writing programs in the Lua language using an additional table of functions, objects, numbers, strings, and "classes" in the namespace table 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++ are for functionss with values passed by reference 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 preferrably 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.

5.1 - Naming, location, and usage of the wxWidgets objects declared in the C++ header files in the wx Lua table

6 - 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.

6.1 - 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 from the executable. See also wxLua Applications for more information about these programs.

6.2 - Provided Samples

7 - 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.

8 - wxLua Utils

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

9 - 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 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".

10 - 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 its 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 its 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 its 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 its 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 its 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.
      • luaI_openlib(L, binding_namespace, fake luaL_Reg, 0) ; is called to have Lua create the tables that we will install the bindings into. This allows wxLua to look like a standard Lua library even though it works a little differently.
        • LUA_REGISTRYINDEX["_LOADED"][binding_namespace] = table
        • LUA_GLOBALSINDEX[binding_namespace] = table
        • LUA_GLOBALSINDEX["package"]["loaded"][binding_namespace] = table
      • wxLuaBinding::DoRegisterBinding(...) is called to actually push the bindings into the binding_namespace table we've created in Lua.
  4. At the end of creation a wxLuaEvent is sent with the wxEVT_LUA_CREATION event type.

10.1 - Data stored in Lua's LUA_REGISTRYINDEX table

wxLua stores its book keeping data in the Lua's 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. A list of all of the tables is at the top of the wxlstate.h header file.

10.2 - Functions to Create a wxLuaState

10.3 - Using a wxLuaState