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
- Version
Information
- Requirements
- Introduction
to Lua
(very brief)
- Bit
Library
- Programming
in wxLua
- wxLua
Samples and How
to Run Them
- How to Run
the Samples
- Provided Samples
- wxLua
Applications
- wxLua
- wxLuaFreeze
- wxLuaEdit
- wxLua Utils
- bin2c.lua
- wrapmodule.wx.lua
- wxLua
Sourcecode Modules
- wxLua C++
Programming Guide
- Data
stored in Lua's LUA_REGISTRYINDEX table
- Functions
to Create a wxLuaState
- Using a
wxLuaState
Version
Information
- The wxLua
version number is set to the stable version of
wxWidgets that it has been updated to. It should also compile with
newer versions of wxWidgets as well as older ones.
- Lua
5.1.3
- wxLua
uses an unmodified copy of Lua 5.1.3 (with patches applied)
- Any
program
that works using the official
release of Lua will work in wxLua.
- wxWidgets
2.8.7 (>= 2.6.3)
- The interface
files have #ifdefs for 2.4, but
they are not maintained anymore since in some cases the complexity of
maintaining backwards compatibility is not worth it and it is better to
take advantage of the fixes and additions to newer versions of
wxWidgets. With a little work you may be able to resurrect it to
work with wxWidgets 2.4.
- Note for wxWidgets
< 2.9 :
wxLua makes use of the wxStyledTextCtrl contrib library
in wxWidgets/contrib/src/stc. You need to have compiled this into a
library if you want to compile the wxLua apps. In wxWidgets >=
2.9 the wxStyledTextCtrl is now part of the main library.
- The
wxLua library links to these wxWidgets libs: stc, xrc, html, media,
adv, net, xml, core, base, tiff, jpeg, png, zlib, regex, expat.
- See
install.html for more 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.
- Comments
- Line comments are marked by -- rest of line is
commented
- Block Comments are --[[
multiple line comment ]]
- Variables
- Variables are not permanently typed and you can
freely
overwrite
them with other values or types, there is no "const" keyword.
- Variables are global unless you put the keyword
"local" in front of them, this is sometimes good practice.
- The
scope of local variables is limited to the current
scope and it's children.
- Local variables can be
harder to debug because they are stored on the stack and you need the
Lua debug
functions to resolve the name.
- A local
variable created with the same name as a global
variable only temporarily supersedes the global.
- Use
the function type(var_name) to
get the variable type as a string.
- "nil",
"boolean", "number",
"string", "table",
"userdata", "function"
- Lua
Types
- nil
: A special value meaning NULL or
nothing.
- Variables that are not
assigned a value are nil and can
be reset back to nil at any time.
- This value is
often returned for functions that fail.
- You can
provide an inline alternative to nil using the 'or' keyword since nil
evaluates to false.
- print(tonumber("a"),
tonumber("a") or 1) -> prints "nil 1"
- boolean
: true or false, nil works as
false, but the number 0 evaluates as true.
- Note: "a = 0; if a
then print(a) end"
evaluates "a" to
true since it has a value, i.e. not nil, use "a ~= 0".
- number
: All numbers in Lua are double
valued floating
point numbers.
- mynumber =
(1E1+ 2e-2 * 3.14 / (4 * 1)
)*math.pow(2.5e+2, 4)
- Variables can be
coerced into numbers using the
function tonumber(variable) which returns nil
on failure.
- Additional math functions are in the math
table.
- string :
Strings in Lua can have
embedded nulls "\0" and use the same escape characters as C.
- Strings are internally hashed by Lua so that
there is only one
copy
of a particular string stored at any one time no matter how many
variables reference it.
- mystring = "How
are 'you'!" or mystring
= 'How\tare "You"!\n' are both valid since either " or ' can
be used
to quote strings. ('\t' = tab, '\n' = line feed)
- mystring
= [[How are
"'you'"!]]
means take everything
including new lines and whitespace literally.
- Concatenate
two strings using the .. operator
- str1
= "hello"; str2 = "number"; str3 =
str1.."
"..str2.." "..tostring(2).."!"
- Numbers
can be typically coerced into strings as ("A
"..1), but not (1.." A") since in the
second case the string "A" cannot be coerced into a number.
- If
many strings need to be concatenated together it is best to insert them
into a table using table.insert() and then call table.concat() to
create the
single output string. The reason why the concat operator .. is slower
is that it requires an allocation of memory for each new string and
then it must be hashed. The table.concat() method's speed is quite
competitive to other scripting languages.
- Variables
can be coerced into strings using the
function tostring(variable) which returns nil
on failure.
- Additional string functions are in
the string
table.
- table :
Tables can be indexed by
numbers, strings,
functions, other tables...
- mytable
= {} a default empty table,
you must declare a variable as a table before using it's indexes.
- mytable = { ["index1"] = 1, "first value",
"second
value", index2 = 2 }
- print(mytable.index1,
mytable["index1"],
mytable[1],
mytable[2], mytable.index2, mytable.index10)
- Outputs
this : "1, 1, first value, second value, 2,
nil"
- Set values as : mytable.index1 =
2;
mytable["index10"] = 3; mytable[10] = 4
- New
values that don't already exist are automatically
created
- Clear values by setting them to nil
: mytable.index1
= nil
- The length operator #mytable
returns 2 since there are only two contiguous numeric table indexes
starting from 1 even though in this case there are actually 4 entries
in the table. Lua table arrays have a starting index of 1.
- Note: Functions
defined by Lua are placed into tables,
a namespace if you will, to keep the global namespace uncluttered.
- See table.XXX, string.XXX, math.XXX, os.XXX etc.
in the Lua
documentation.
- wxLua places the wxWidgets
bindings into the wx.XXX
table "namespace".
- The global table is called _G
and you can display it
or any table using (k = key, v = value)
- for
k, v in pairs(_G) do print(k, v) end
- userdata :
- This is a C/C++ pointer to an object that by itself
cannot be used in Lua.
- A metatable (see Lua documentation) may be
assigned to it to allow it to act like a table or be called like a
function, among other things.
- This
is the datatype that wxLua uses wrap wxWidgets C++ objects
that are pushed into Lua. The metatable that is assigned to the
userdata when created determines what type of C++ object and therefore
what functions are available to be called on it.
- function
:
- function SumDiff(a, b)
print(a, b);
return a+b, a-b end
- num_sum,
num_diff = SumDiff(2, 3)
- Can
return multiple values and be passed less or more
variables
than specified. The unhandled returns or inputs are set to nil
or if
there are extra thrown out.
- Variables can be
assigned to functions if desired or
functions can be put into tables
- PrintWarning
= function(msg) print("Warning:
"..msg) end
- FuncTable = {};
FuncTable["Warning"] =
PrintWarning; FuncTable.Warning("I'm broke")
- Values passed to functions are local
copies and not
modified unless they are tables or userdata
- function AppendToTable(atable, val)
atable[#atable+1] = val end
- mytable
= {}; AppendToTable(mytable,
"hello")
adds "hello" to index 1, i.e. mytable[1] == "hello"
- Note that the table is not returned, but modified
in place, also note that we can use table.insert() to append to
a
table instead of the above method.
- Operators
- Relational : == ~= < > <=
>=
(Note: not equal is ~=)
- Logical: and,
or,
not
- Precedence (low to high):
- or
- and
- < > <= >= ~= ==
- ..
- + -
- * / %
- not #
- (unary)
- ^
- Keywords
- and break do else elseif end false for function
if in
local nil not or repeat return then true until while
- do ... end
- Create a new local scope in a do end block.
- Note : You cannot write function
printHi() return; print("hi") end, but you can have function
printHi() do return end; print("hi") end which can be useful
for debugging functions.
do
-- create a new local scope
local a = 2
end
- if
(bool) then ...
elseif (bool) then ... else ...
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
- while
(bool) ...
end
- Note : there is no continue
keyword
only break
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
- You
can make a
"fake" continue by adding a while loop (doesn't
print # 5).
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
- repeat
... until
(bool)
- Note : there is no
continue keyword only break
local a = 1
repeat
local temp = a * 2
print(temp, type(temp))
a = a + 1 -- no increment operator
until a > 10
- for
var = init_value,
end_value [, increment] do
... end
- Note : there is no
continue keyword only break
- You cannot modify the
loop variable, limit, or increment from within the loop. The
loop counter variable is local to the
loop and the final print(a) statement below will print that a = "hello"
as
it did before the loop.
- Copy the loop counter variable to a separate
variable if you need to save it when breaking for example.
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
- functions
- Input any number of values by value, tables and userdata
are
passed by
reference
- Missing input variables are assigned
the value nil, extra inputs are discarded.
- Return
values using the "return" keyword
- Not all return
values need to be used and extra ones will be discarded.
- The
symbol "_"
is a valid variable name and is often used as a dummy variable to
receive return values that you do not want.
- function GetNums()
return 3, 4 end; local _, num2 = GetNums()
- You
may also use the select(n,
...) function to choose return values to use.
- Tables
can be used as containers for input values to functions using the
unpack(table, [i, [, j]]) function. This is useful for creating complex
inputs to a function or storing them for reuse.
- print(string.find(unpack({"Hello",
"ll", 1, 1}))) -> prints "3 4"
- Vararg
inputs are written as function
dostuff( ... )
- The number of
args is found using: local
n = select("#", ...)
- The args can be
converted into table using: local
args = { ... }
- A particular arg can be
chosen using: local
arg3 = select(3, ...)
- Note
select(n, ...)
returns
all args after n,
but if the left hand side is a single variable the others are
discarded. See above about using select()
to pick return values of a function as well.
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.
- bit.bnot(a)
returns the one's complement of a
- bit.band(w1,...)
returns the bitwise and of the w's
- bit.bor(w1,...)
returns the bitwise or of the w's
- bit.bxor(w1,...)
returns the bitwise exclusive or of the w's
- bit.lshift(a,b)
returns a shifted left b places
- bit.rshift(a,b)
returns a shifted logically right b places
- bit.arshift(a,b)
returns a shifted arithmetically right b places (works on negative
numbers too)
- bit.mod(a,b) returns the integer
remainder of a divided by b
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.
- bit
- The bit
library from Reuben Thomas for manipulating integer bits.
- wxlua
- Special
functions for introspecting into wxLua or generic functions that wxLua
provides that are independent of wxWidgets.
- wx
- wxWidgets
functions, classes, defines, enums, strings, events, and
objects are placed here.
- wxaui
- The wxWidgets Advanced User Interface
library.
- wxstc
- The
wxStyledTextCtrl wrapper around the Scintilla text editor.
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
- #define
NUMBER_DEFINE VALUE
- All
#defined numerical values are available as wx.NUMBER_DEFINE
- Example "#define wxID_ANY -1" is
accessed as wx.wxID_ANY
- Declared
in the bindings using the %define
tag
- [int,
double, etc] NUMBER_VARIABLE;
- All
global numerical variables are available as wx.NUMBER_VARIABLE
- Example : "extern const int wxInvalidOffset;"
is accessible as wx.wxInvalidOffset.
- Declared
in the bindings using the %define
tag
- enum ENUM_NAMESPACE [or
CLASSNAME::ENUM_NAMESPACE] { ENUM_NAME }
- All global enums, named or not, are available as wx.ENUM_NAME
- Example : "enum wxDirection { wxLEFT,
... }"
is accessible as wx.wxLEFT
- All
enums that are members of classes are available as wx.CLASSNAME.ENUM_NAME
- Example : "enum wxFTP::TransferMode {
ASCII, ... }" is accessible as wx.wxFTP.ASCII
- This follows the C++ semantics that you do not
have to
specify the name of an enum, but you do have to use its scope if it is
a class member.
- Declared in the bindings using
the %enum
tag
- #define
STRING_DEFINE wxT("String Value")
- All
#defined string values are available as wx.STRING_DEFINE
- Example : "#define
wxIMAGE_OPTION_CUR_HOTSPOT_X wxT("HotSpotX")" is
accessible as wx.wxIMAGE_OPTION_CUR_HOTSPOT_X
- Declared in the bindings using the %define_string
tag
- const wxChar*
STRING_VARIABLE;
- All global
string variables are available as wx.STRING_VARIABLE
- No examples yet.
- Declared in the
bindings using the %define_string
tag
- wxEVT_XXX
for wxEvtHandler::Connect()
- All
wxEVT_XXX wxEventTypes (an integer) are
available as wx.wxEVT_XXX
- Example : wx.wxEVT_COMMAND_MENU_SELECTED
for menu item selection.
- wxLua
does not use the static event tables since it is
not a compiled language. Rather the wxEvtHandler::Connect() function is
used
to connect event types to a wxEvtHandler, typically a wxWindow
derived class. Therefore you do not use EVT_XXX() macros, but the
corresponding wxEVT_XXX. The wxluaref.html manual contains a complete
mapping between the two.
- Example : EVT_MENU(id,
func) use window:Connect(menuId,
wx.wxEVT_COMMAND_MENU_SELECTED, Lua function). The Lua
function must have the signature of "function
MenuEvent(event) ...
handle event ... return" where the event variable will be of
the wxEvent class
the wxEventType was declared in, which in this case is a
wxCommandEvent.
- Example
: EVT_PAINT(func)
use window:Connect(wx.wxEVT_PAINT, Lua function).
There is no id used for this connect event
function call since you are directly connecting the paint event to the
window, whereas in the menu case you are handling a menu event
from the menu that travels up the chain of window parents until a
handler is found, therefore you need the Id to determine where
the
event came from.
- Note: You must
always create a wxPaintDC for wxEVT_PAINT.
- local
dc =
wx.wxPaintDC(event:GetEventObject():DynamicCast("wxWindow"))
and then call dc:delete()
at the end of the function because the paint event clears the
"dirty" region to repaint and if it is not cleared another paint event
will be sent... and so on.
- Declared
in the
bindings using the %define_event
tag
- Objects
of classes or structs OBJECT_NAME
- All
global objects that are classes or structs are
available as wx.OBJECT_NAME
- Example
: "const wxImage wxNullImage;"
is accessible as wx.wxNullImage and functions from
the wxImage class can be called as wx.wxNullImage:Ok()
which should
return false.
- Declared in the bindings using the %define_object
tag
- Pointers to
classes or structs POINTER_NAME
- All
global pointers that are classes or structs are
available as wx.POINTER_NAME
- Example
: "extern wxPenList*
wxThePenList;" is accessible as wx.wxThePenList
and
functions from the wxPenList class can be made as "pen =
wx.wxThePenList:FindOrCreatePen(wx.wxColour(1,2,3), 1, wx.wxSOLID)"
- Declared in the bindings using the %define_object
tag
- Global C
style
functions
VAR_TYPE FUNCTION_NAME(int a, const wxString& str)
- All global C style functions are available as wx.FUNCTION_NAME(1,
"Hello")
- Example : "extern
wxString
wxGetUserHome(const wxString& name)" is accessible as
"home_dir = wx.wxGetUserHome("john")"
where wxString means to input a Lua string and a Lua string is
returned.
- Declared in the bindings using the %function
tag
- C++ Classes
CLASS_NAME
- All C++ classes
are available as wx.CLASS_NAME,
however in order to use one you must call one of the constructors first
or get the class as a return value from another function call.
- Example : "pt = wx.wxPoint(1,
2); pt2 = wx.wxPoint(pt)".
- Multiple member functions
with the same
name are overloaded as in C++ and
the proper function to call
is determined at runtime. This is one of the reasons why wxLua is
stricter about type than Lua. For example; string arguments do
not accept numbers which Lua would silently convert.
- Member functions from
the
base class(es) are also available
and may be overloaded as well.
- The C++ classes
are exposed as tables in Lua, but have a __call
metatable item so they can be called as a function. If you need to get
the
constructor function itself you can use wx.CLASS_NAME.new(...)
which is the constructor exposed as a Cfunction.
- The
C++ class objects are pushed into Lua as a userdata wrapping a void*
pointer to the C++ object.
- A special metatable
is set on the userdata with these entries :
- __index to call functions on the object or
to get member variable values.
- __newindex to set new functions or values or set
member variable values.
- __tostring to allow print() to show something useful
- print(wx.wxPoint()) "userdata: 0x858df5c
[wxPoint(0x84ab550, 251)]", where 0x858df5c is the Lua userdata
address, 0x84ab550 is the address of the wxPoint object, and
251 is the wxLua type that wxLua uses to determine that this Lua
userdata wraps a wxPoint. The wxPoint type may not always be 251 since
it depends on the number and order in which the bindings were
initialized.
- __gc to tell wxLua when the userdata is no longer
used so wxLua can delete the C++ object if appropriate.
- Declared
in the bindings using the %class
tag
- Deleting
class userdata can be done using the wxLua added class
member function delete().
- All classes
that have the %delete binding tag will be eventually garbage collected
when they go out of scope.
- Classed without the
%delete tag are assumed to be eventually attached to another object
that will delete them for you.
- The Lua garbage
collector uses an incremental collector that waits until the data size
reaches a limit and slowly removes them to avoid program slowdown. This
is a good thing and makes Lua programs run at an even pace.
- However!
Some graphical device interface (GDI) classes need to be deleted
immediately when you are done with them.
- This
is really a MS Windows problem, in Win95 based systems the number that
you could create was severely limited, but even in NT systems (XP, Vista) you
will have problems if you've created hundreds of them. One visible sign
that something is wrong is when controls, like menus, stop redrawing
themselves properly and the program becomes sluggish.
- In
any case, just delete() them when done so that your program will work
equally well in MSW as it would in Linux or OSX.
- Additionally,
since the Lua userdata that wxLua pushes into Lua only store a void*
pointer to the C++ class object, Lua only
thinks they are of size void* which are on 32bit x86 machines only 8
bytes.
However, the class might store a 1024x768 x 3 bytes/pixel
image as a wxImage (2.36Mb). There have been a number of
discussions about this on the Lua mailing list, but currently there is
no way to let Lua know the true size of a userdata to help it better
decide when and what to garbage collect. The core of
Lua could be modified, but that would make it harder to use wxLua as a
loadable module.
- The solution is to use the delete()
function on certain types of userdata when you are done.
- Care must be taken to ensure that you're not silently
creating too many temporary objects.
- Example: "wxDC:SetPen(wx.wxPen(wx.wxColour(1,2,3),
1, wx.wxSOLID))"; notice that both a wxPen and a wxColour
have been created, but there is no way for you to call delete() on them
so they will collect until Lua runs its garbage collector.
- You can force garbage collection using "collectgarbage("collect")"
in Lua, but this may cause pauses in your program's execution. It is a
good idea to collect all the garbage at the end of your initialization
function to at least start out with a clean slate since program
startup time is usually not a concern.
- This
is a list of classes by order of importance of deleting them
- Must delete :
wxDC, wxPaintDC, and ALL classed derived from wxDC
- Must
delete if > 50 :
wxBitmap, wxBrush, wxColour, wxCursor, wxFont, wxIcon,
wxPen, wxRegion
- To
be sure, delete them when you're done and not worry.
- Must delete
if large and you're creating many of them : wxImage
- Don't
bother : wxPoint, wxRect... etc
- Never delete :
wxWindows attached their their parents (use Destroy()), wxMenuItems
returned from a wxMenu.
- Safe rule,
don't
delete() things that aren't yours. Refer to the wxWidgets documentation
about whether an object will take ownership of an object passed to
it.
- How to tell how
many userdata objects you currently have?
- Print the output of wxlua.GetGCUserdataInfo(true) to show what objects will be garbage collected when their reference count goes to 0 and the Lua garbage collector runs.
- Print the output of wxlua.GetTrackedObjectInfo(true) to get class objects that wxLua has pushed into Lua that may or may not be garbage collected.
- Call
the function wxlua.LuaStackDialog() when you run
your program and examine the items in the Lua LUA_REGISTRYINDEX table.
Expand "wxLua objects pushed" and "wxLua gc objects to delete" tables.
- Member functions
of the class are called using the colon ':' convention and NOT the
period
'.'.
This is because ':' in Lua puts the object itself on the
stack, the
"self" as it's called, and this is used by the binding code to call the
function with. If you really
want to use the '.' notation you can pass the "self" in as the first
parameter. There are two exceptions to the ':' calling convention rule,
properties
and static
functions, please see the sections below about why they only use the
'.' convention.
- Example : "size
= wx.wxSize(1, 2); size:SetWidth(10); size.SetHeight(size, 11);
print(size:GetWidth(), size.GetHeight(size))" where we create
a
wxSize, set a new width and height, and then print the numerical values.
- Functions may be renamed in the bindings using the %rename
tag in the interface files. You call the functions using the name after
the %rename tag with the same parameters as the
original function. This is only done for special cases that
would be awkward, if not impossible, to wrap otherwise.
- Property functions
allow
you to read and/or write values to a class using the '.' convention and
a shortened name.
- These are generated
on the fly when the function
is
called on a wxLua userdata and work only for functions
following these rules.
- GetXXX()
takes no values and returns one.
- SetXXX(value)
takes one value and
returns none.
- The Get/Set part of
the
function name is removed leaving only XXX and you
do not call them like
a function using "()", but rather like accessing a table
member, without the "()".
- Example
: "rect
=
wx.wxRect(wx.wxPoint(1,2), wx.wxSize(3,4)); rect:SetX(20); rect.X = 10;
print(rect.X, rect.X == rect:GetX(), rect.X == rect.GetX(rect))"
should print "10, true, true".
- Note : There is no
way to find out from Lua if the
code used
a '.' or a ':' to call the function and therefore properties cannot be
made to work for the ':' calling convention since in that case
we have to remove the object (the self) that Lua automatically pushes
onto the stack that we don't need or want.
- Note :
Since these methods are generated at runtime they will not work for
static functions in the class table, but they will work for static
functions called from a userdata object.
- Below is
a
list of what works and doesn't, the example is for a static function,
but the same works for a regular class member function.
- Works
(static functions only) : "print(wx.wxFileName.GetCwd())"
and "print(wx.wxFileName.GetCwd)"
prints that it's a function.
- Fails (static
functions only) : "print(wx.wxFileName:GetCwd())"
and "print(wx.wxFileName:GetCwd)"
- Works
: "f =
wx.wxFileName("a"); print(f.GetCwd())" and "print(f.GetCwd)"
prints that it's a function.
- Fails
: "f =
wx.wxFileName("a"); print(f:GetCwd())" and "print(f:GetCwd)"
- Works : "f
= wx.wxFileName("a");
print(f.Cwd)"
- Fails : "f
= wx.wxFileName("a");
print(f.Cwd())" and "print(f:Cwd)"
and "print(f:Cwd())"
- Note :
Are properties really
necessary? Confusing? Useful?
I'd stick with the Get/Set functions. - JL
- Member
variables allow you
to read and/or write to member variables of a class.
- Declared in the interface files using the %member
or %member_func tag.
- Example : In the
interface file gdi.i
this is
declared for wxPoint : "%rename X %member_func int x"
- The wxPoint class does not have functions to access
the int x, y variables so we create our own.
- The %member_func
tag creates functions
called Get/Set[variable name] or in this case Getx() and Setx(value),
but these aren't too pretty so we use the %rename
tag to rename them to GetX() and SetX(value). It additionally creates
properties for the x variable so the '.' calling convention also works.
- These two methods of getting and setting the x and y
member
of the wxPoint class are interchangeable.
- Example : "pt =
wx.wxPoint(1,2); pt.x = 10; pt:SetY(11); print(pt.x, pt:GetY())"
- If the %member tag is
used (as opposed to the %member_func) the Get/Set
functions are not generated and the member variables are accessible
only through the properties.
- If the member
variable is constant (const) the
variable is read-only and you cannot set it's value.
- Static
functions are part of the
table that holds the class and can be called with or without a class
instance (a userdata).
- Example : f
=
wx.wxFileName('dummy');
f.GetCwd() == wx.wxFileName.GetCwd()
- Note
that you always use the '.' calling convention since
static C++ functions do not require the object itself or in Lua's case
the userdata.
- See the properties
section
about the difference between '.' and ':' and why using a ':' cannot be
made to work reliably when you don't want or need the self pushed onto
the stack.
- Enum members
are also part of
the
table that holds the class and are used by accessing the class table
itself.
- Example : "enum
wxFTP::TransferMode {
ASCII, ... }" is accessible as wx.wxFTP.ASCII
- Operator functions
allow you to use
C++ operators in Lua.
- Lua has a
limited set of operators, see the Lua
primer, whereas C++ can define many more. Also, not
all C++ operators are
defined for all classes and very few classes can be mixed
with other classes. Operators for classes must be declared
in C++. Therefore Lua uses functions to call these operators rather
than try to directly modify the existing ones in Lua and then
declare the remaining ones as functions.
- Note
also that declaring
every operator for all classes in wxLua is usually not necessary
because in C++ they typically shadow an existing function that wxLua
already wraps.
- The Lua = operator for a class
object will merely
create a reference to the object and this itself is useful and why
wxLua does not try to override the default behavior.
- Declared
in the interface files
using the %operator
tag.
- "==" = "op_eq"
- "!="
= "op_ne"
- "<" = "op_lt"
- ">" = "op_gt"
- "<="
= "op_le"
- ">=" = "op_ge"
- "|" = "op_or"
- "&"
= "op_and"
- "||" = "op_lor" note:
"lor"
stands for logical (boolean)
or,
same for "land."
- "&&"
=
"op_land"
- "!" = "op_not"
- "^" = "op_xor"
- "++"
=
"op_inc"
- "--" = "op_dec"
- "-
(unary)" = "op_neg"
- "=" = op_set
- "+" = "op_add"
- "-" =
"op_sub"
- "*" = "op_mul"
- "/"
= "op_div"
- "+=" =
"op_iadd" note: ixxx stands for "inplace" as
it modifies the original object.
- "-=" =
"op_isub"
- "*="
= "op_imul"
- "/=" =
"op_idiv"
- "%=" = "op_imod"
- "&=" = "op_iand"
- "|="
= "op_ior"
- "^="
= "op_ixor"
- Example : "pt =
wx.wxPoint(1,2); pt = pt +
1" gives an error since we're trying to use the Lua operator
and even in C++ this wouldn't compile since there is no operator
defined for adding a single number to a wxPoint.
- Example
: "pt1 = wx.wxPoint(1,2); pt2 =
pt1; print(pt2:GetX()); pt2:SetX(10); print(pt1:GetX(), pt1 == pt2)"
the = operator works in this case because we are not copying the values
of pt1, but rather the address of pt1 to pt2, meaning that pt2 is
pt1 and when we set the value for pt2 we're also setting the value for
pt1. We know this because the Lua == operators tells us that they have
the same address and if you type "print(pt1, pt2)"
the result is "userdata: 0x858df5c [wxPoint(0x84ab550, 251)],
userdata: 0x858df5c [wxPoint(0x84ab550, 251)]". See the wxLua
userdata metatable function __tostring above.
- Example : "pt1 =
wx.wxPoint(1,2); pt2 =
wx.wxPoint(); pt2:op_set(pt1); pt1:SetX(10); print(pt2:GetX());
print(pt2:op_eq(pt1))" creates pt1 and also creates pt2, but
we don't care what value it has since we use op_set to use the C++ =
operator to copy the values from pt1. We then change the value of pt1,
test if pt2 has changed, it hasn't, and the test to see if they're
still equal and as expected, they're not.
- Virtual functions
- You
cannot
arbitrarily override C++ virtual functions
in wxLua as this must be done in C++. The C++ class must be subclassed
and
the virtual functions overridden to check to see if there is a Lua
function to call instead of the base class function. This has only
been done for cases where it is necessary. In many cases you can
intercept the appropriate wxEvent and change the behavior from within
the handler.
- Examples of virtual functions that
must or can be
overridden are in the wxLuaPrintout class, see the printing
sample, and wxLuaHtmlWindow, see html sample. The only virtual
functions that you can override are marked with comments in the binding
files and wxluaref.htm.
- Prepend the function name
with an underscore, '_' in order to directly access the C++ base class
function that you have overridden in Lua.
- Adding
virtual functions to
wxLua will be done on a case by case basis. If it is absolutely
necessary to override a virtual function for a class you should ask
about adding it on the wxLua mailing list. The reason why they have not
already been added is that there is a price to pay in terms
of binding size and speed.
- Overriding
member functions with Lua functions
- You
may override class member functions for a wxLua userdata and still be
able to call back to the Cfunction by prepending the function name with
an underscore '_'.
- The Lua function that you
assign
to a userdata will be called directly from Lua without regard to the
existing Cfunction(s), but will never be called by the C++ class
functions.
- Example : "p
= wx.wxPoint(1,2); p.GetX =
function(self) return 10-self:_GetX() end; print(p:GetX(), p:_GetX())"
prints "9, 1".
- Note : Make sure that if you want
to
call the base function you use the '_' in your overridden function
since otherwise you'll get
recursion.
- Extending
classes
- You
may add your
own functions to classes that
will not be called by C++, but can be called from Lua. This makes sense
if you would like to keep functions that act on a particular class with
it rather than having global functions that take that class as a
parameter.
- Example : "r =
wx.wxRect(1,2,3,4); r.PrintXY = function(self) print(self:GetX(),
self:GetY()) end; r:PrintXY()" adds the function PrintXY() to
the wxRect instance r. The userdata, class instance, r is
passed to the Lua function as the parameter "self" which is pushed onto
the stack when the PrintXY() function is called with the ":" notation.
- Note
that the above example is the same as "r
= wx.wxRect(1,2,3,4); function wxRect_PrintXY(r)
print(r:GetX(), r:GetY()) end; wxRect_PrintXY(r)".
- You
may also create the Lua function beforehand and
then assign it to the rect object. "function
wxRect_PrintXY_func(self) print(self:GetX(), self:GetY()) end;
r1 = wx.wxRect(1,2,3,4); r1.PrintXY = wxRect_PrintXY_func; r1:PrintXY()".
You can see that using this idea you can write a Lua function
that creates a new wxRect, sets your extra functions
for it, and returns it for use.
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.
- On
the command line run $wxlua.exe
sample.wx.lua
- On the command line
run $wxluafreeze.exe
sample.wx.lua
- Open the Lua program in wxlua.exe
and choose
the menu item Run.
- Open the Lua program in wxluaedit.exe
and
select the menu item wxLua->Run or press the toolbar "play"
button to run it.
- Use
wxLua as a Lua module (using the function require), run $lua.exe sample.wx.lua
- In order to use wxLua as a module the Lua code must have require("wx") to load the wxLua bindings in the beginning and wx.wxGetApp():MainLoop() at the end to start the wxWidgets event loop.
- You may need to adjust the package.cpath variable to have it point to the correct location of the wx.so or wx.dll shared library for require("wx") to load.
Provided
Samples
- bindings.wx.lua
- This is a MUST use program, at least once, to get a
better understanding of the bindings.
- Lets you
explore the C++ binding structs from within Lua
using a wxListCtrl. This program shows the raw data that is used to push the
bindings into Lua when a wxLuaState is created.
- Take
note of the menu item "Show Lua stack dialog..." and the code for it.
You can use this dialog to debug your own programs by viewing the
stack, local and global variables, as well as the Lua registry which is
only accessible in C.
- calculator.wx.lua
- A
simple calculator program that demonstrates loading and
using controls from an
XRC resource, accelerator tables, and event handling. This programs
loads the file calculator.xrc to create it's GUI.
- choices.wx.lua
- Demonstrates
a number of controls that offer choices to
the user, wxRadioBox, wxListBox, wxComboBox, wxChoice, and
wxCheckListBox. It uses a wxNotebook and wxSizers for layout.
- coroutine.wx.lua
- A
demo of how to use coroutines in wxLua using wxEVT_IDLE to call
coroutine.resume().
- dialog.wx.lua
- A simple temperature conversion program to/from
Fahrenheit to/from Celsius. Shows the use of wxSizers, wxButtons, and
the wxTextCtrl.
- editor.wx.lua
- This is the editor that the wxLua application apps/wxlua
uses. It uses the wxStyledTextCtrl for the editor and can run and debug
Lua programs. For more information see the wxLua application notes
below.
- grid.wx.lua
- A
very simple demo of the wxGrid class. A better
one would be appreciated.
- htmlwin.wx.lua
- Shows the wxLuaHtmlWindow and it's virtual
functions as
well
as adding.custom widgets to a wxHtmlWindow.
- luamodule.wx.lua
- A
sample for loading the wxLua "wx" module using Lua's require
function when wxLua is compiled as a shared library. Run this program
using the Lua executable and not wxLua or wxLuaFreeze since the wxLua
library is loaded at run-time. See also wrapmodule.wx.lua
for more information about loading Lua modules.
- mdi.wx.lua
- Shows
the MDI classes, wxMDIParentFrame and
wxMDIChildFrame.
- media.wx.lua
- A sample for the wxMediaCtrl that can load and
play audio
and video files.
- minimal.wx.lua
- A minimal sample that creates a wxFrame,
wxMenuBar, and
wxStatusBar.
- printing.wx.lua
- Demonstrates how to use the printing architecture
and
some wxDC
drawing classes in wxLua.
- scribble.wx.lua
- A simple drawing program that shows how to handle
wxMouseEvents
and
wxDC drawing as well as creating a custom control.
- sizer.wx.lua
- A
simple wxSizer demonstration.
- tree.wx.lua
- A wxTreeCtrl demonstration.
- unittest.wx.lua
- Tests
that the binding generator is working properly as well as wxLua itself.
- This
is also a good reference for how to call various objects since it tries
to test all the valid methods.
- validator.wx.lua
- Tests the wxGenericValidator and wxTextValidator.
- veryminimal.wx.lua
- wxluasudoku.wx.lua
- A complete Sudoku solver and program to
play
Sudoku puzzles. This program demonstrates most things that might
be required for typical GUI programs; drawing, printing,
event handling, custom dialogs, key and mouse events, menu, toolbar,
statusbar, etc...
- The program is broken into two
parts and the code put in
two separate Lua tables to make things easier to understand. The sudoku
solver code is in the "sudoku" table at the top of the listing and the
wxWidgets GUI code in the "sudokuGUI" table at the bottom.
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
- This
is a wxLua IDE editor program written in Lua that has a
nice editor using the wxStyledTextCtrl.
- The Lua
code for it is in samples/editor.wx.lua
- You can
fully debug Lua programs, step through them line
by
line, set break points, view call stack, etc.
- The
File, Edit,
and Search menus offer typical editor functionality.
- The Debug menu contains the items to
run and debug your programs
- Compile
- test compilation of your
program, does not
run it, but checks the Lua syntax.
- Run
- Run the current program independently in a separate
process.
- The wxLua program is run
with the command '$wxLua
editor_filename' and therefore you need to have saved it to
disk.
- Attach
- Attach the debugger to a
process, you must
start the debuggee process by hand by running another wxLua process as
"wxLua -dHOSTNAME:PORT program.lua" using the appropriate values for
HOSTNAME:PORT as shown in the wxLua status window after selecting Attach.
You can abort the debugging by selecting Stop
Debugging.
- Start Debugging
- Start debugging
the
current program where
you can then Step, Step Over, Continue, Break.
- A TCP debugger server is started on a port in the
range 1551-1559 listening for a connection from the localhost.
- A new wxLua process is created (see Attach) as a
debuggee client and the code in the current editor is sent to the
debugee to run.
- Console
- Use a dialog with a text
control to show the output from Lua print statements when
running or debugging programs.
- Stop
Debugging - Stop debugging and
close the
debuggee process.
- Step - Take
one step in debugging
the program.
- Step Over - Step
over a function
call.
- Step Out - Step out of a
function
call.
- Continue - Continue
running the
program.
- Break - Break a
running program.
- View Call Stack
- View the current
call stack of a Lua
program being debugged showing all variables and their values.
- View Watches - Set and view watches
of variables for
the Lua program being currently debugged.
- Show
Output Window - Show or hide
the output window for messages during debugging.
- Clear
Output Window - When checked,
clear the text in the output window when starting to debug.
- This
program can also run Lua or wxLua programs on the
command line just like the Lua executable.
- The
command line switches can be displayed by running
wxLua -h.
- The editor is run if no parameters are
given.
- Note that the switches -c (print console),
-q (don't
quit if no top level window open), -e (execute Lua code) must be
specified
before -d, -o, -r
- The switches -d (run as
debuggee), -o (open files to
edit), and -r (run file) are exclusive and you can only use one.
- If -d, -o, or -r are not given but there is at
least one parameter on the command line, it is interpreted to be a
program name and wxLua will try to run it, any parameters after the
program name are pushed into the Lua as a table named 'arg'.
- wxLua editor.wx.lua is the
same as
just running wxLua itself. You can run the
editor this way to customize it, but please don't forget to
post any enhancements to the wxlua-users mailing list so they can be
incorporated back into wxLua.
- If you
want to run a program or provide arguments to
your Lua program that use -X or /X semantics you need to use
-- to stop the wxLua program from interpreting the args.
- In the example below, we don't want wxLua to
interpret the second -c or give an error for the -g arg, but
rather pass the args to myprogram.lua.
- wxLua
-c -e "a = 12; b = 3" -- myprogram.lua
-c 12 -g
- The
wxLua program will display a console window to
display print statements, run the string "a = 12; b = 3", then
run myprogram.lua and push into lua a table named 'arg' with the
indices
- [-5] = 'd:\wxLua\bin\wxlua.exe', [-4]
= '-c', [-3]
= '-e', [-2] = 'a = 12; b = 3', [-1] = '--', [0]
= '../samples/unittest.wx.lua'
- [1] = '-c', [2] =
'12', [3]
= '-g'
- This is the same table the Lua executable
creates, where arg[0] is the name of the Lua program run and positive
indices
are args to the Lua program and the most negative index is the name of
the executable.
- wxLua -c -e "a = 12;
b = 3" -r myprogram.lua -- -c 12
-g
- Gives the same results, but the
Lua arg
table starts with [1] = '--' which should probably be ignored.
-
wxLuaEdit
- This is another IDE type program written in C++
that runs
wxLua
programs in the main thread and can therefore be "dangerous." However
it works fairly well and uses wxYield events to keep the editor GUI
responsive while running, though this does sacrifice speed. It
does not allow step-by-step debugging of Lua programs. However, it does
provide a
Lua shell to try things out very quickly and you can interactively
manipulate or introspect a program as it runs in the "Output" window.
- Run wxLua Program -
Runs the program
in the current notebook tab and outputs any print or error messages to
the "Output" window. A new lua_State is created for each run and is
accessible in the Output window until a new one is run.
- Stop
wxLua Program
- Stops the
currently running wxLua program. This only stops the program if Lua is
actually running meaning that the Lua parser is running. Once you've
created a top level window the wxWidgets event system runs in the
background and calls the wxLuaState as necessary for event handling.
This is why Lua is considered to be not running even though your
programing
is "running."
- Stack Tree -
Show the stack of the
current lua_State. Current means which output window you're looking at,
either the Shell or the Output.
- Toggle
Breakpoint - Add a breakpoint
to the line of code and when the Lua parser reaches it throw an error.
You can then use the print() statement in the Output window or the
stack tree to view the current state of Lua. You cannot view local
variables however and apparently this is a limitation of Lua itself.
You cannot also continue running the program.
- The
editor uses
the wxStEdit library from wxcode.sourceforge.net for the editor. You
need to download either the newest version or use CVS to get a copy
from wxcode.sourceforge.net in order to compile this editor.
-
wxLuaFreeze
- This is the simplest incarnation of
a wxLua program
that
makes use of the wxLua library. Once compiled, it can run Lua programs
on the command line as $wxLuaFreeze program.lua.
Additionally you can use the wxluafreeze.lua script
to append a single
file Lua program to the end of wxLuaFreeze to run. Please
see readme.txt in apps/wxluafreeze
and
also either run wxluafreeze.lua with no arguments
or read the the
Usage() function in it. You should give the output of wxluafreeze.lua
a
new name so you don't modify the original, though you may do this if
you like. Once a program has been "frozen" to the end of wxLuaFreeze it
automatically runs it and any arguments passed to it on the command
line
are pushed into Lua as the args table. For MSWindows a program called
upx can be used to compress the executable to about 1.5 Mb from 4.5 Mb,
using VC6 in release mode as the compiler.
wxLua
Utils
Utility programs for wxLua are located in the wxLua/util
directory.
-
bin2c.lua
- bin2c.lua
is a Lua program to convert a file into a const
char* string to be included into a C/C++ program.
- You can then run the
script in C++ by calling wxLuaState::LuaDoBuffer(string_var,
string_len, "Lua program").
- Help is shown if no arguments are
given when run or you can read its Usage() function.
-
wrapmodule.wx.lua
- This
is a wrapper program to allow you to use the wx shared library as a Lua
module (using require) to run the provided samples without having to
edit them.
- See How
to
Run the Samples for other ways to run the samples.
- The
search path for the module may need to be specified if it is not in the
same directory as the sample you want to run.
- You
can add a line like the one below to the top of wrapmodule.wx.lua
(adjusted as
necessary) for your paths.
- The list of paths is a
semicolon separated list of paths to ?.so (for Unix type
shared libraries) and ?.dll
(for MSW) .
- ? is equivalent to * meaning match
anything for typical shells (DOS prompt).
- You
might
as well include paths to both unfix and MSW libraries so that the script
can be run on either platform without modification since typically only
the libraries that work on any given platform will be installed.
- package.cpath
=
";;../lib/?.so;../lib/vc_dll/?.dll;../lib/bcc_dll/?.dll;../lib/mingw_dll/?.dll;"
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".
- lua
- The
source code of Lua itself. It is the
original
unmodified source for the version, with some of the header files copied
to the
include directory for the installation routines.
- Patches released for
the version are applied as they come out, see wxLua/docs/changelog.txt.
- Compilation of this module generates a Lua library and
two executables, lua.exe and luac.exe.
- wxbind
- The
output of the interface files in wxLua/bindings/wxwidgets
are generated in this directory. They are the wrappers for the
wxWidgets
library.
- You do not need to regenerate them unless you have
edited the interface files themselves.
- You should NOT edit these files
directly as they will be overwritten if you regenerate the bindings,
the fix should really go into the interface files themselves.
- To initialize this library in a C++ program and have it
pushed
into Lua you should
have the code "extern bool wxLuaBinding_wxXXX_init();"
and then somewhere in your app initialization or at least before you
create a wxLuaState call wxLuaBinding_wxXXX_init().
This is because different compilers seem to have problems with the
various techniques we've tried to automatically initialize the binding
and may even
throw out the whole library when linking unless you explicitly use
something in it. Replace the XXX with the name of the library you want
installed, see modules/wxbind/include/wxbinddefs.h for a list of them.
- You should preferably use the macros in modules/wxbind/include/wxbinddefs.h to make it easy to install a standard set of
them or all of them. They do some simple checks to determine if the binding will be available based on the wxWidgets wxUSE_XXX directives.
- Compilation of this module
generates a number of
libraries corresponding to the libraries that wxWidgets
generates, wxadv, wxaui, wxbase, wxcore, wxgl, wxhtml,
wxmedia, wxnet, wxstc, wxxml, and wxxrc.
- wxlua
- This
is the core library of wxLua itself. It contains the
wxLuaState class and helper functionality.
- You must at least link to
this library.
- The public C++ side of wxLua is
almost entirely contained
in modules/wxlua/include/wxlstate.h.
- This
library also contains some bindings that are useful
for debugging and getting information about wxLua.
- To
initialize this
library in a C++ program and have it pushed into Lua you should
have the code "extern bool wxLuaBinding_wxlua_init();"
and then somewhere in your app initialization or at least before you
create a wxLuaState call wxLuaBinding_wxlua_init().
- Compilation of this module generates a wxlua library.
- wxluadebug
- This
is a simple debug library for Lua that provides some
tools and a widget for showing the stack and browsing the locals,
globals, and registry variables.
- Compilation
of this module generates a wxluadebug library.
- wxluasocket
- This is a socket library for one wxLua program to
communicate with another for debugging purposes. It is currently used
in
the wxlua app (samples/editor.wx.lua).
- This lib
depends on the wxluadebug
lib.
- To initialize this
library in a C++ program and have it pushed into Lua you should
have the code "extern bool wxLuaBinding_wxluasocket_init();"
and then somewhere in your app initialization or at least before you
create a wxLuaState call wxLuaBinding_wxluasocket_init().
- Compilation of this module generates a wxluasocket
library.
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.
- 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.
- The
function wxLuaState::Create(L, wxLUASTATE_USESTATE) is called to finish
setting up the lua_State.
- 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.
- 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.
- 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.
- We
register a print() function for Lua to get the output of Lua print()
statements to send messages as wxLuaEvents, see
wxEVT_LUA_PRINT.
- The bindings are
registered by calling wxLuaState::RegisterBindings().
- Each
binding that is loaded are derived wxLuaBinding
classes whose member data variables point to structs in each binding. A
single static instance of each binding class are installed
into a wxList when the
wxLuaBinding_XXX_init() functions
are called. The reason behind the need for running the init function
from the binding libraries is to stop certain compilers from throwing
out the whole binding library, which happens even if the binding was
added to the list from within the library.
- 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.
- 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
- wxLuaState(bool create = false)
- If create is false, default constructor, you must call
Create(...) to actually use it.
- If create is
true, you now have a
working wxLuaState, i.e. a lua_State, with all the bindings attached.
- wxLuaState(wxEvtHandler *handler, wxWindowID id
= wxID_ANY)
- Creates a complete
wxLuaState, but you can
provide an
event handler, e.g. a wxApp or wxWindow derived class, to
get and handle the wxLuaEvents, see also Get/SetEventHandler().
- wxLuaState(lua_State* L, wxLuaState_Type type = wxLUASTATE_GETSTATE)
- type = wxLUASTATE_GETSTATE means that the lua_State must
already have been created using a wxLuaState and so this new wxLuaState
will merely attach to the corresponding ref data.
- type
= wxLUASTATE_SETSTATE means that this new lua_State
that you have created will have the wxLua bindings pushed into it if wxLUASTATE_OPENBINDINGS is set and
then be ready for running wxLua programs. The wxLuaState will not close
the lua_State, but will remove itself from Lua and do cleanup when
there are no more instances of them if wxLUASTATE_STATICSTATE is set.
Using
a
wxLuaState
- int LuaDoString(const wxString &script,
const
wxString& name = wxEmptyString)
- Runs
the script as a string with the given name. The name
is only used if Lua errors out and then the debug message will contain
that name.
- Returns Lua's error code LUA_ERRXXX
or 0 on success
- int
LuaDoBuffer(const
char *buffer, size_t len, const char
*name)
- Run a buffer, perhaps from
bin2lua.lua, that you've
compiled with your program.
- Returns Lua's error
code LUA_ERRXXX or 0 on success
- int
LuaDoFile(const wxString &filename)
- Run
a Lua file from disk.
- Returns Lua's error code
LUA_ERRXXX or 0 on success
- int
LuaPCall(int narg, int nresults)
- Uses
lua_call to run a chunk on the stack, but sets
things up for wxLua first.
- Returns Lua's error
code LUA_ERRXXX or 0 on success
- There are many
other functions which are documented in wxLua/modules/wxlua/include/wxlstate.h.