The binding generator for wxLua provides information for Lua code to interface to a C/C++ API. The C/C++ objects are created in Lua as userdata and manipulated using the same functional semantics as you would in C/C++. The wxLua manual, wxlua.html, describes in detail how the object will be named and where it will be placed in Lua.
wxLua has binding files for the wxWidgets cross-platform GUI library and the wxStyledTextCtrl contrib library of the wxWidgets library. The binding generator is flexible enough to be used to create bindings for other projects. This allows wxLua to be integrated as a scripting language in C++ projects. There is an example in the wxLua/apps/wxluacan
directory.
The interface files are stripped down skeletons of C/C++ header files. The program bindings/genwxbind.lua
parses these files and generates C functions that are exposed to Lua by a generated wxLuaBinding
derived class. The whole process of generation is automatic and no editing of the output files should be attempted. If there are any problems, the interface files or the generator should be fixed. Some examples of the interface files are in the bindings/wxwidgets/*.i
directory. Before writing your own, take some time to examine them and note the differences between them and the original C++ code. If the automatic bindings do not generate suitable code for a specific function you can %override
individual function bindings with your own code to implement it in any way you want.
bindings/wxwidgets/wxbase_rules.lua
(for example) is a rules file that determines where and what interface files genwxbind.lua
should read, how it should name the generated classes and output files, what extra header code to add, among other things. Documentation for creating a rule file is in each of the ones provided by wxLua and you should copy one to use as a starting point for your own.genwxbind.lua
runs before processing the interface files, but after it has created various structures used for parsing allowing for customization by either adding to the structures or changing them.lua -e"rulesFilename="wxwidgets/wx_rules.lua"" genwxbind.lua
datatype_cache_input_fileTable
variable of the rules file.typedefTable
, dataTypeTable
, and preprocConditionTable
variables of the genwxbind.lua
program.bindings/wxwidgets/wx_datatypes.lua
file which may be used by external bindings that use datatypes declared in the wxLua wxWidgets bindings.bindings/wxwidgets/wx*_rules.lua
file will generate its own wx*_datatypes.lua
datatype file, but these are gathered together into the wx_datatype.lua
file for use by others.wxLUA_USE_XXX
for C++ compilation of the wxWidgets bindings.wxLUA_USE_XXX
is 1 then it's compiled in and will be accessible to wxLua scripts, else skipped when compiling the binding cpp files to create a smaller library.wxUSE_XXX
#defines control what parts of wxWidgets is available to wxLua programs.wxColour
class by #defining wxLUA_USE_wxColourPenBrush=0
then all functions that take or return a wxColour
will be excluded. The best thing to do is to test things out and see what works for you.override_fileTable = { "override.hpp" }
Functions that take pointers or references and return values through the variables passed in must be reworked to return multiple values.
In order for the %overload
functionality to work and to get the proper signatures; the function parameters in the .i file should match the actual parameters that the %override
code implements. The interface files for wxLua always have these three lines, where the first line is for documentation purposes only, the second line is the original C++ function declaration for reference, this is what wxWidgets expects to get, and the third line is the correct calling semantics for the %overridden
function.
// %override void wxFrame::SetStatusWidths(Lua table with number indexes and values)
// C++ Func: virtual void SetStatusWidths(int n, int *widths)
virtual void SetStatusWidths(LuaTable intTable)
The binding generator genwxbind.lua
generates a number of files and you can specify both their names and directories.
wxLuaBinding_[hook_cpp_binding_classname]_init()
.
It is probably easiest to declare the function using extern bool wxLuaBinding_[hook_cpp_binding_classname]_init();
in your C++ file rather than including the header.
wxLuaBinding
derived class that is added to a static wxList of bindings. There should only be one of the binding classes created as they all share the same structures anyway.static wxLuaBindingList* wxLuaBinding::GetBindingList()
can be used to iterate through the bindings, if needed.Note: A variety of different ways to automatically initialize the bindings were tried that would invariably fail with certain compilers, but work with others. Having to call the init function before creating a wxLuaState seems to work everywhere as it guarantees that when the bindings are compiled as a library, at least something in it is used and the linker won't throw the whole lib out.
int s_wxluatag_CLASS_NAME
, for each class that are mapped through the wxLuaBindClass struct. When the binding is initialized, a unique the tag index will be assigned to the class for marking the Lua userdata wrapper with its type.int ClassMethodFunction(lua_State* L)
, that are called for the class methods.wxLuaBindMethod
struct for each class to map the method function names to the C functions.wxLuaBindEvent
struct that contains all the wxEventType
values and their associated wxEvent
classes to push into the Lua binding table.wxLuaBindDefine
struct that contains all the numerical values to push into the Lua binding table.wxLuaBindString
struct that contains all the strings to push into the Lua binding table.wxLuaBindObject
struct that contains all the objects to push as userdata into the Lua binding table.wxLuaBindMethod
struct that contains all the global C functions to push into the Lua binding table.wxLuaBindClass
struct that contains the class names, all the wxLuaBindMethod
structs from each *.i generated cpp files, and their tags.wxLuaBinding
derived class that actually pushes the bindings into Lua.The only way to handle C++ virtual functions in wxLua is to subclass the C++ class you want to be able to write Lua functions for and bind the subclassed version. The hand coded wxLuaPrintout
class is a good example of this. Below is a description of how the C++ code and Lua work to allow overriding a C++ virtual class member function from Lua.
The wxWidgets class wxPrintout
has a number of virtual functions, but lets focus on virtual bool wxPrintout::OnBeginDocument(int startPage, int endPage)
as an example, since if you override this function you must also call the base class function for printing to operate correctly. The source code for the class wxLuaPrintout located in modules/wxbind/include/wxcore_wxlcore.h
and modules/wxbind/src/wxcore_wxlcore.cpp
and you should review it before reading further. You will also need to look at samples/printing.wx.lua
to see the Lua code that overrides the function and modules/wxlua/wxlbind.cpp
for the metatable functions Lua uses to handle a call to a function.
Below is a list of the function calls for wxPrintout::OnBeginDocument()
and notes about how it all works.
wxLuaPrintout
in Lua, replace the function OnBeginDocument()
with our own function in Lua, and begin the printing process, perhaps doing a print preview. The code for this is in the printing.wx.lua
sample.virtual wxPrintout::OnBeginDocument(...)
, but we've subclassed wxPrintout and so its function wxLuaPrintout::OnBeginDocument(...)
gets called.
wxLuaPrintout
keeps a refed copy of the wxLuaState
from when it was created since otherwise the function wxLuaPrintout::OnBeginDocument()
wouldn't know what lua_State
is active since wxWidgets doesn't know anything about wxLua.wxLuaPrintout
instance, in order to find the correct lua_State. This can impose a large performance penalty if there are multiple states and/or a large number of userdata objects.wxLuaPrintout::OnBeginDocument()
we first check to see if wxLuaState::GetCallBaseClassFunction()
is true, if not, check to see if wxLuaState::HasDerivedMethod(this, "OnBeginDocument")
is true, where this is the particular instance of the wxLuaPrintout
class.
OnBeginDocument()
we'll use it. First push the wxLuaPrintout
and the parameters to the function that's already been pushed on the stack by a successful call to wxLuaState::HasDerivedMethod()
when it calls wxLuaObject::GetObject()
. Call it and then get the result, if any, pop the result, and reset the stack to the starting point.wxPrintout::OnBeginDocument(...)
explicitly.wxLuaPrintout
, but rather wxPrintout
since wxLuaPrintout
is a hollow shell that merely forwards calls to Lua or to the base class.
_OnBeginDocument(...)
on the wxLuaPrintout
userdata object, the function wxluabind__index_wxLuaBindClass(...)
in modules/wxlua/wxbind.cpp
is called. This is the function that handles all function calls for wxLua userdata objects. It performs a lookup to see if the function exists and pushes it onto the stack for Lua to call after this function has returned.wxLuaState::Set/GetCallBaseClassFunction()
to remember if the Lua function was called with a preceding "_".GetCallBaseClassFunction()
from within our derived C++ virtual class function is that wxWidgets may immediately call another C++ virtual function, but the wxLuaState is still flagged to call the base class and so calls to functions like wxLuaPrintout::OnPrintPage(...)
fail since they are directed to call the base class function and not our derived Lua functions.To summarize, here's the function calls and where in each function wxLuaPrintout::OnBeginDocument()
is when you override the function in Lua.
wxLuaPrintout::OnBeginDocument(...)
in C++.wxLuaPrintout::OnBeginDocument(...)
runs the code to call the derived Lua function OnBeginDocument(...)
by calling wxLuaState::LuaCall()
on it. (GetCallBaseClassFunction() and HasDerivedMethod() are both true)wxluabind__index_wxLuaBindClass(...)
is called when, in Lua, the function _OnBeginPrinting()
is called for the wxLuaPrintout
userdata. The flag wxLuaState::GetCallBaseClassFunction()
is set to true, and the C function wxLua_wxPrintout_OnBeginDocument()
(in modules/wxbind/src/wxcore_print.cpp
) is run by Lua which calls back to wxLuaPrintout::OnBeginDocument(...)
.wxLuaPrintout::OnBeginDocument(...)
a second time, the first time through is still stalled at wxLuaState::LuaCall()
running Lua's OnBeginDocument()
function, but this time we just call wxPrintout::OnBeginDocument()
and return.wxLuaState::LuaCall()
function finishes and the first call to the function wxLuaPrintout::OnBeginDocument(...)
returns.These parameters are interpreted by the generator to implement code to handle a few special cases so we don't have to write overrides for them.
wxArrayString& choices
or wxArrayString* choices
, the generator will not perform the table conversion, but will require a wxArrayString userdata since it's assumed that the C++ function will modify the wxArrayString that's passed to it for the caller to use as a return value.wxArrayInt& choices
or wxArrayInt* choices
, the generator will not perform the table conversion, but will require a wxArrayInt userdata since it's assumed that the C++ function will modify the wxArrayInt that's passed to it for the caller to use as a return value.dir = wx.wxFileName.DirExists("/some/dir")
orf = wx.wxFileName(); dir = f.DirExists("/some/dir")
The descriptions below use wx
the name of the binding table in Lua. Other bindings would, of course, use their own tables.
%alias
class [%delete] ClassName [: public BaseClassName [, public BaseClassName2]]
{
ClassName(...)
member functions
...
};
ns::ClassName
, the class must be declared as class [...] ns::ClassName
and the constructor must also be declared as ns::ClassName(...)
. The generator will change the "::" to "_" for use in Lua.wxPoint
should be deleted when there are no longer any references to it, but wxWindows
are typically attached to a parent and the parent wxWindow
will delete its children, not Lua.wxPoint
or ref-counted wxObject
dervied classes like wxPen
are often returned by C++ functions on the stack. wxLua will make a 'new' object, copy the value using the C++ '=' operator, and set a flag that this new object is to be deleted when the Lua garbage collector calls the wxLua collection function.#define NUMBER_NAME [Value]
wx.NUMBER_NAME
.#define A_DEFINE 1
.bindings/wxwidgets/defsutils.i
.#define_object OBJECT_NAME
#define_pointer POINTER_NAME
#define_string STRING_NAME [Value]
#define_wxstring STRING_NAME [Value]
enum [Enum_Type or ClassName::Enum_Type or Namespace::Enum_Type]
{
ENUM_ITEM1
ENUM_ITEM2
...
};
functions : return_type FUNCTION_NAME(int value, ...)
%gc
%gc_this
#if wxLUA_USE_XXX && %__WXMSW__
Interface file data...
#endif // wxLUA_USE_XXX
#include "headerfile.h"
%includefile interfacefile.i - DEPRECATED and probably does not work
member variables of classes : int m_x
%member_func int m_x
operators for classes : bool operator==(const wxPoint& otherPt) const
The reason that the operators are not overridden in Lua using the metatable is that Lua only defines a limited set of operators. Having some operators overridden and some not is probably more confusing that not overriding any. Secondly, the Lua operators, the '=' and '==' operators (for example) are useful as userdata pointer assignment and pointer comparisons respectively. This is equivalent to using pointers in C, as in *"wxPoint pt = &otherPt", which merely increases the ref count of the object and is useful as is.
This is a list of all possible operator functions:
Relational and equality operators | ||
== | op_eq() | |
!= | op_ne() | |
> | op_gt() | |
< | op_lt() | |
>= | op_ge() | |
<= | op_le() | |
Logical operators | ||
! | op_not() | |
&& | op_land() | "l" stands for logical |
|| | op_lor() | |
Bitwise operators | ||
~ | op_comp() | bitwise NOT or complement |
& | op_and() | |
| | op_or() | |
^ | op_xor() | |
<< | op_lshift() | |
>> | op_rshift() | |
Inplace bitwise assignment operators | ||
&= | op_iand() | "i" stands for inplace |
|= | op_ior() | |
^= | op_ixor() | |
>>= | op_irshift() | |
<<= | op_ilshift() | |
Arithmetic operators | ||
= | op_set() | |
+ | op_add() | |
- | op_sub() | |
* | op_mul() | |
/ | op_div() | |
% | op_mod() | |
Unary arithmetic operators | ||
- | op_neg() | |
Inplace arithmetic assignment operators | ||
+= | op_iadd() | |
-= | op_isub() | |
*= | op_imul() | |
/= | op_idiv() | |
%= | op_imod() | |
Increment arithmetic operators | ||
++ | op_inc() | |
-- | op_dec() | |
Other operators | ||
[] | op_index() | Array indexing |
() | op_func() | Function call |
* | op_deref() | Dereference/Indirection |
%not_overload int FUNC_NAME(int value)
%override wxLua_ClassName_FunctionName
// any code or comments can go within the %override ... %end block
static int LUACALL wxLua_ClassName_FunctionName(lua_State* L)
{
...
}
%end
%override_name CFunctionNameTheOverrideUses
%rename NEW_FUNC_NAME void FUNC_NAME()
%skip
struct [%delete] StructName
{
member variables
...
};
ns::StructName
, the struct must be declared as struct [...] ns::StructName
and the constructor must also be declared as ns::StructName(...)
. The generator will change the "::" to "_" for use in Lua.typedef KNOWN_DATATYPE UNKNOWN_DATATYPE
typedef
the binding generator would give an error about an unknown data type, since it would assume that a typo or an error in the interface file had been made.%ungc
%ungc_this
%wxchkver_X_Y_Z
%wxcompat_X_Y
Standard wxWidgets #defines for conditional use using the #if directive
%__WINDOWS__
%__WIN16__
%__WIN32__
%__WIN95__
%__WXBASE__
%__WXCOCOA__
%__WXWINCE__
%__WXGTK__
%__WXGTK12__
%__WXGTK20__
%__WXMOTIF__
%__WXMOTIF20__
%__WXMAC__
%__WXMAC_CLASSIC__
%__WXMAC_CARBON__
%__WXMAC_OSX__
%__WXMGL__
%__WXMSW__
%__WXOS2__
%__WXOSX__
%__WXPALMOS__
%__WXPM__
%__WXSTUBS__
%__WXXT__
%__WXX11__
%__WXWINE__
%__WXUNIVERSAL__
%__X__
%__WXWINCE__
%wxEventType wxEVT_XXX
class
tag for the wxEvent derived class it corresponds to so the event's methods can be known to Lua and the generator can assign the correct class type to it.