http://wwhiz.com/LuaPlus/index.html
The LuaPlus distribution contains some modifications to the core Lua code base. As such, it is not an official distribution of Lua 5.0, nor does it intend to represent itself as one. Most modifications are superficial, but some, such as the wide character string type, touch a little more code. Any references to Lua in this document refer specifically to the modified Lua code contained herein, unless otherwise stated.
This documentation is very incomplete at this time.
The LuaPlus distribution provides the following functionality. The reasons for the additions are noted with each line item.
LUA_TSTRING
in the Lua core code base was supplemented with an
equivalent wide character LUA_TWSTRING
.The LuaPlus Visual Studio LuaWatchAddin provides facilities whereby the Watch window
will show the contents of a LuaObject
, LuaTableIterator
,
LuaStackObject
, LuaStackTableIterator
, or
TString
(when
stepping inside Lua internals). The LuaWatchAddin does not expand Lua
tables, but an additional add-in does.
Program Files/Microsoft Visual
Studio .NET/Common7/IDE
.Program Files/Microsoft
Visual Studio .NET/Common7/Packages/Debugger/autoexp.dat
:; LuaPlus LuaPlus::LuaObject=$ADDIN(LuaWatchAddin.dll,AddIn_LuaObject) LuaPlus::LuaStackObject=$ADDIN(LuaWatchAddin.dll,AddIn_LuaStackObject) LuaPlus::LuaStackTableIterator=$ADDIN(LuaWatchAddin.dll,AddIn_LuaStackTableIterator) LuaPlus::LuaTableIterator=$ADDIN(LuaWatchAddin.dll,AddIn_LuaTableIterator) TString=$ADDIN(LuaWatchAddin.dll,AddIn_TString)
LuaPlus::LuaObjects
, LuaPlus::StackObjects, LuaPlus::LuaTableIterators
,
LuaPlus::StackTableIterators
and
TStrings
will expand in the watch
window.
The LuaWatchAddin does not provide expansion for Lua tables, although the LuaPlus Debugger Add-in does.
The ManagedLuaPlus Watch window support currently only works for
LuaObject
.
Program Files/Microsoft
Visual Studio .NET/Common7/Packages/Debugger/mcee_cs.dat
:; LuaPlus <ManagedLuaPlus.LuaObject>=<WatchType>
The LuaPlus Visual Studio .NET Debugger add-in allows viewing of Lua tables in a tree fashion. Currently, there is no installer for this.
To manually install:
All LuaPlus functionality is encapsulated in the LuaPlus namespace. Any
references to LuaPlus classes and types in this documentation assume the LuaPlus::
qualifier.
LuaState
is the C++ form of a lua_State
. Most C functions that accessed
a lua_State
are inlined functions in LuaState
. As far as efficiency goes,
LuaState
is equally as fast as the C
low-level counterparts for most operations.
LuaPlus is set up to work in DLL or LIB form, therefore, special
functions are provided for creating and destroying LuaState
objects. It is
not possible to new
a LuaState object, because it is
necessary to ensure all allocation and deallocation is done within the same
memory management system. It is also not possible to call the core Lua
lua_open()
function and use a lua_State
pointer from
it.
The static function LuaState::Create()
is used to create a LuaState
instance.
The Create()
function provides the ability to initialize the Lua
standard library, which consists of the auxiliary, base, debugging, I/O, math,
ANSI string, wide string, and table libraries. If the application is using
LuaPlus strictly for data purposes, the standard library should probably
not be initialized.
An alternate approach to creating and destroying a LuaState
object is shown below, in the LuaStateAuto/Owner
class.
LuaState* state = LuaState::Create();
LuaState
Thread InstanceTo add another state, typically for thread purposes, to an existing LuaState
instance, use the LuaState::CreateThread()
static function.
LuaState* threadState = LuaState::CreateThread(state);
LuaState
InstanceCalling the LuaState::Destroy()
function runs all final garbage collection
processes and frees any memory associated with the LuaState
object.
LuaState::Destroy(threadState); LuaState::Destroy(state);
lua_State
Pointer to a LuaState
InstanceA special function called LuaState::CastState()
exists for purposes of
changing an underlying lua_State*
to a LuaState*
. Note that
CastState()
can only be used if the lua_State
pointer was originally from a
LuaState::Create()
call. This separation may occur with certain Lua
callbacks.
LuaState* castedState = LuaState::CastState(regular_lua_State);
Global variables in a LuaState
instance may be retrieved by one of a couple
methods.
LuaObject obj = state->GetGlobal("MyGlobalVariable");
Alternatively, the basic LuaObject::operator[]
referencing or
the LuaObject::GetByName()
functions may be used in conjunction
with LuaState::GetGlobals()
. (Both functions are described in
greater detail below, in the LuaObject
section.)
LuaObject globalsObj = state->GetGlobals(); LuaObject obj = globalsObj["MyGlobalVariable"];
You can also use a shortened form:
LuaObject obj = state->GetGlobals()["MyGlobalVariable"];
Note that some functions are for retrieval of LuaStackObjects
. These
function names are usually followed with _Stack
.
LuaStackObject obj = state->GetGlobal_Stack("MyGlobalVariable");
LuaStateAuto
is an auto pointer encapsulation for a LuaState
pointer.
When the LuaStateAuto
goes out of scope, LuaState::Destroy()
is
automatically called on the contained state. In a Release build, LuaStateAuto
's
accessors are inlined, and code generation is as if the LuaStateAuto
object did not even
exist.
Using LuaStateAuto
is illustrated below:
{ LuaStateAuto stateOwner; // The state is automatically set to NULL. stateOwner = LuaState::Create(); stateOwner->PushNil(); // LuaState::Destroy() is automatically called here. }
LuaStateOwner
is derived from LuaStateAuto
.
LuaStateOwner
can automatically create the LuaState
through the function call LuaState::Create
.
{ LuaStateOwner stateOwner; // Automatically calls LuaState::Create(). stateOwner->PushNil(); // LuaState::Destroy() is automatically called here. }
Since a LuaStateAuto
object merely encapsulates the LuaState
pointer, it is
possible to retrieve that pointer by just assigning it.
LuaState* state = stateOwner;
LuaPlus provides an API extension over the core of Lua wrapped in the class
LuaObject
. A LuaObject
gives the full functionality of core Lua's stack
entities, but it does so without involving the stack at all. In general,
LuaObjects
tend to run a little faster than the core Lua stack equivalent.
A LuaObject
should be used for all communication with LuaPlus that is
external to a callback function. LuaStackObjects
, described
below, are used in conjunction with callback functions, but the same functional
interface is provided for consistency.
LuaObjects
store a pointer to the parent LuaState
. In part, this
is what makes the LuaWatchAddin work. Most importantly, LuaObjects
can
just be passed around without any regard for the LuaState they came from.
The sample code TestSuite performs an in-depth test of LuaObject and is a useful supplement to this documentation.
A LuaObject
contains an object of one of several different types. These
types are described in the Lua manual with
the exception of the wide string type, a LuaPlus added type.
There are several ways to retrieve the type of the LuaObject. To test for a specific type, one of the following functions may be called:
IsNil()
IsTable()
IsUserData()
IsCFunction()
IsNumber()
IsString()
IsWString()
IsFunction()
IsNone()
IsLightUserData()
IsBoolean()
Generically, the type may be retrieved via the GetType()
function. It returns a value from the LuaState
class's
enumeration of Types:
The actual string name of the type can be retrieved through LuaObject
's
GetTypeName()
function.
After testing the LuaObject
for the desired type, the stored
value may be retrieved using one of LuaObject
's Get*()
functions. All Get*()
functions assert on the wrong type in
Debug builds.
int GetInteger()
float GetFloat()/GetNumber()
double GetDouble()
const char* GetString()
const wchar_t* GetWString()
lua_CFunction GetCFunction()
void* GetUserData()
void* GetLightUserData()
bool GetBoolean()
If the LuaObject
is an ANSI or wide character string, the length
of the string in characters may be retrieved via StrLen()
.
For objects of type table, function, userdata, or light userdata, the
internal Lua storage pointer can be retrieved via the function
GetLuaPointer()
.
LuaObject obj = state->GetGlobal("SomeVariable"); if (obj.IsString()) { const char* str = obj.GetString(); }
For a stack Lua value, the programmer uses Push*()
functions to
get user values on the stack. Since LuaObjects
aren't stack
based, an alternate mechanism was devised.
To assign a value to any LuaObject
, use one of the
Assign*()
functions.
AssignNil()
AssignBoolean(bool value)
AssignNumber(double value)
AssignString(const char* value)
AssignWString(const wchar_t* value)
AssignUserData(void* value)
AssignLightUserData(void* value)
AssignObject(LuaObject& value)
AssignNewTable(int narray = 0, int nhash = 0)
For example, to assign the string "Hello, world!" to a LuaObject:
LuaObject strObj(state); strObj.AssignString("Hello, world!");
Note the constructor argument being passed into LuaObject
.
That argument tells the LuaObject
which LuaState
it
belongs to. Without a LuaState
parent, most parts of
LuaObject
can't function.
When the LuaObject
is a table, the functions for manipulating
tables become available. A few functions exist for retrieving various
types of table counts.
For the following table:
MyTable = { WindSpeed = 50, Value = 'Hello', 10, 20, 30 }
Calling GetN()
returns 3. GetN()
uses Lua's
table.getn()
function internally to retrieve the count.
table.getn()
only considers contiguous numeric keys starting at 1 to be
the count.
GetCount()
also only considers contiguous numeric keys starting
at 1. It would also return 3 for the table above. However, for one
shot table counts, GetCount()
generally runs much faster.
Finally, GetTableCount()
exists to return the actual number of
(non-contiguous) keys in the table. For MyTable
above, the table count would
be 5.
When the LuaObject
is a table, the functions for manipulating
tables become available. If the LuaObject
is not a table and
those functions are used, they will assert.
operator[]
has been overloaded to accept a key type of
const char*
, int
, or LuaObject
. Using
operator[]
allows lookups to be very naturally represented, much
like using Lua script code.
state->DoString("MyTable = { WindSpeed = 50, Value = 'Hello', 10, 20, 30 }"); LuaObject myTableObj = state->GetGlobals()["MyTable"]; LuaObject windSpeedObj = myTableObj["WindSpeed"]; LuaObject is20Obj = myTableObj[2]; LuaObject keyObj(state); keyObj.AssignString("Value"); LuaObject valueObj = myTableObj[keyObj];
Although not usually needed, spelled out forms of the table retrieval functions are:
GetByName(const char* key)
GetByIndex(int index)
GetByObject(LuaObject& obj)
The LuaObject
table setting functions all start with
Set*()
.
There are 3 overloaded Set*()
functions per value type.
Each takes one of three key types for the key-value pair arguments.
const char*
.int
).LuaObject
.The Set*()
functions are listed below. key
is
one of the 3 types listed above.
SetNil(key)
SetBoolean(key, bool value)
SetNumber(key, double value)
SetString(key, const char* value)
SetWString(key, const wchar_t* value)
SetUserData(key, void* value)
SetLightUserData(key, void* value)
SetObject(key, LuaObject& value)
Example:
LuaObject tableObj(state); tableObj.AssignNewTable(); tableObj.SetString("MyKey", "Hello, world!");
On many occasions, it is still necessary to access an object on the Lua
stack. Callback functions receive an array of LuaStackObjects
as arguments. Generally, the APIs for a LuaStackObject
and a
LuaObject
are similar enough to not be an issue when writing code.
LuaObjects
are, however, the preferred way of accessing objects
maintained by Lua, since the stack doesn't need to be taken into consideration.
Turning a LuaStackObject
into a LuaObject
is as
simple as making an assignment:
LuaStackObject stack1Obj(state, 1); LuaStackObject stack2Obj(state, 2); LuaObject nonStack1Obj(stack1Obj); // or LuaObject nonStack2Obj = stack2Obj;
The cases where you would need to push a LuaObject
onto the Lua
stack are rare. Nonetheless, the facility is provided through
LuaObject
's PushStack()
function.
LuaObject tableObj(state); tableObj.AssignNewTable(); tableObj.SetString("Key", "My String"); // It's often good practice to use a LuaAutoBlock here. tableObj.PushStack(); // Be sure to clean it up when you're done!
Proper LuaPlus callbacks are of the function signature:
int Callback(LuaState* state, LuaObject* args);
The primary reason for the args
parameter to exist is for
purposes of display through the LuaWatchAddin. However, the convenience of
being able to index into the arguments with array notation (args[1].GetString()
)
is very appealing, too.
LuaPlus's callbacks use Rich Hickey's functor implementation. The functors mask away the differences between global functions, non-virtual member functions, and virtual member functions.
Lua standard C-style callbacks can also be used, although they aren't as functionally robust as LuaPlus callbacks.
An example follows:
static int LS_LOG(LuaState* state, LuaObject* args) { printf("In static function\n"); return 0; } class Logger { public: int LS_LOGMEMBER(lua_State* L) { printf("In member function\n"); return 0; } virtual int LS_LOGVIRTUAL(lua_State* L) { printf("In virtual member function\n"); return 0; } }; LuaObject globalsObj = state->GetGlobals(); globalsObj.Register("LOG", makeFunctor(LSFunctorType(), LS_LOG)); state->DoString("LOG()"); Logger logger; globalsObj.Register("LOGMEMBER", makeFunctor(LSFunctorType(), logger, Logger::LS_LOGMEMBER)); state->DoString("LOGMEMBER()"); globalsObj.Register("LOGVIRTUAL", makeFunctor(LSFunctorType(), logger, Logger::LS_LOGVIRTUAL)); state->DoString("LOGVIRTUAL()");
Make note of the makeFunctor()
function. For all LuaPlus
callbacks, functors are created with makeFunctor()
. In fact,
all LuaPlus makeFunctor()
calls must have the first argument be
LSFunctorType()
. This is a limitation of Rich Hickey's
functor library, but since his functor library was created in 1994, we'll give
him a break. :)
Callback functions are registered with the Register() function. LuaObject provides several overloaded Register() functions:
void Register( const char* funcName, lua_CFunction function ); void Register( const char* funcName, LuaStateCFunction function ); void Register( const char* funcName, LSFunctor functor ); void Register( const LuaFunctionList* functionList ); void Register( const LuaFunctorList* functionList );
LuaObject provides a wide range of function registration facilities, including standard Lua callbacks and non-functor LuaPlus-style callbacks. Additionally, arrays of functions may be registered, too.
Unfortunately, at this time, LuaObject does not fully support closures with upvalues, although closures may be obtained through the LuaStackObject interface.
LuaObject attempts to simplify the function calling interface of the core Lua API. It does so by completely masking away the stack management. Often, Lua function calls with arguments can be performed in a single line of code.
To do this, LuaPlus employs a convention similar to the Standard C++ library's iostream functionality. A simple example follows:
LuaStateOwner state; state->DoString("function Add(x, y) return x + y end"); LuaObject funcObj = state->GetGlobal("Add"); { LuaAutoBlock autoBlock(state); LuaStackObject retObj = funcObj() << 2 << 7 << LuaRun(); printf("Add: %d\n", retObj.GetInteger()); }
The function call starts by "calling" the LuaObject
.
LuaObject
provides an overloaded function operator(). Then, each
argument to the function is added to the argument list, left to right.
Finally, when all arguments are added, LuaRun()
executes the
function call.
It can't be avoided that a Lua function call puts return values on the stack.
The LuaStackObject
returned by the LuaPlus function call is the
first return value. There may be more.
operator<<
understands most Lua types. The nil
type is special, though. In order to tell LuaPlus a nil should be inserted
in the function's argument list, LuaArgNil()
must be passed in.
LuaObject funcObj = state->GetGlobal("PrintIt"); LuaStackObject retObj = funcObj() << "String" << LuaArgNil() << LuaRun();
LuaRun()
takes an optional argument detailing the number of
return values allowed. By default, multiple return values are allowed.
LuaObject funcObj = state->GetGlobal("ThreeReturnValues"); LuaStackObject retObj = funcObj() << LuaRun(1); // Only accept one return value.
Fill me in.
LuaPlus does not use integers to represent stack objects. Instead,
those integers are wrapped in a LuaStackObject
. LuaStackObjects
can be passed
directly to a Lua C function, if needed, but it is advised to go through the
LuaPlus version of the function.
Using a LuaObject
is usually the better way to go, since a LuaObject
relieves
the user of any stack management at all. LuaStackObjects
are available for
use in callback functions or in special case stack management scenarios.
LuaStackObjects
also store a pointer to the parent LuaState
. In part, this
is what makes the LuaWatchAddin work. Most importantly, LuaStackObjects
can
just be passed around without any regard for the LuaState
they came from.
Most LuaStackObject
functions mirror LuaObject
functions of the same name, so
see the section above for more detail.
(Note: Using LuaObject, there is little to no need to use this class.)
LuaPlus enhances the Lua ref table facility by allowing ref'ed objects to be
used without using GetRef()
to push them onto the stack.
LuaRefObject
encapsulates this new functionality. Assigning a LuaObject
(or another
LuaRefObject
) to a LuaRefObject
instance will cause a
lua_ref()
to occur.
When the LuaRefObject
goes out of scope, lua_unref()
is called.
LuaRefObject
is derived from LuaObject
and can operate on ref'ed objects without
issue.
The LuaWatchAddin displays the contents of LuaRefObjects
.
LuaPlus provides a class called LuaTableIterator
to ease the table iteration
process. Its use is far simpler, safer, and more natural looking than the
standard Lua table iteration function (lua_next()
/lua_pop()
). The iterator
is not STL compliant in its current form.
LuaStateMaster state; state.DoString( "MyTable = { Hi = 5, Hello = 10, Yo = 6 }" ); LuaObject obj = state.GetGlobals()[ "MyTable" ];for ( LuaTableIterator it( obj ); it; it.Next() ) { const char* key = it.GetKey().GetString(); int num = it.GetValue().GetInteger(); }
If the LuaWatchAddin is installed, the key and value portions of the LuaTableIterator object will be displayed as it is traversed.
LuaTableIterator is fully documented in LuaPlus.h.
A LuaStackTableIterator is almost identical to the LuaTableIterator above, except it provides support for iterating using the stack, similar to how core Lua does it.
LuaStackTableIterator is fully documented in LuaPlus.h.
Nothing can be more frustrating than paying attention to stack management.
Which function allocates which entry on the stack? How many entries?
Did it get popped? Where is that stack leak at? LuaAutoBlock
serves
as a fairly useful approach to solving these problems.
LuaAutoBlock
is a C++ class whose constructor stores the index of the stack
top. At destruction time, it sets the stack top to the stored index.
By providing this functionality as an object, the stack is guaranteed to be
restored, regardless of exit points from a function or loop block.
Note: When using the LuaObject class, there is no need to worry about stack management, and so LuaAutoBlock provides no benefits in that situation.
{ LuaAutoBlock autoBlock(state); LuaStackObject testObj = state->GetGlobals_Stack()["Test"]; // Does this allocate a stack item? state->PushString["A string"]; // Does this? testObj.SetNumber("Value", 5); // Does this? // Who cares? LuaAutoBlock automatically cleans it up. }
LuaStateOutFile
and derived classes are used in conjunction with
LuaState::DumpObject()
. When a LuaStateOutFile
object is passed to
DumpObject()
, that object is used for writing the Lua dump file.
The application can derive from LuaStateOutFile
to change the
default dumping behavior.
The LuaHelper namespace contains some useful helper functions for retrieving values from LuaObjects. The helper functions perform a lookup into a table for a certain key. If the key is required to be found and is not present, an assertion is triggered. Otherwise, the found value or a default value is returned.
The following helper functions are available:
GetBoolean()
GetFloat()
GetLightUserData()
GetString()
GetTable()
Wide character support is built-in as a native LuaPlus type. While it is entirely possible to represent a wide character string using a regular Lua 8-bit clean string, there is no way of determining whether the given string is wide or not. The secondary problem involves the use of standard string functionality, such as the concatenation operator. If a wide character string is represented as a normal 8-bit Lua string, special functions would have to be written to perform operations on the string (i.e. concatenation of two Lua 8-bit clean strings which represent wide characters). Rather than require the user to keep track, a wide character string type is available.
Wide character strings can be entered into Lua script similar to the approach used by C code.
L"Wide characters"
By inserting an L
in front of the quote, the LuaPlus lexer creates a wide character
representation of the above string. If the string was entered as a regular Lua string,
the Unicode equivalent would be simulated as follows, and the string below
assumes a certain architecture's endianness.
"W\000i\000d\000e\000 \000c\000h\000a\000r\000a\000c\000t\000e\000r\000s\000\000\000"
In the event it is necessary to insert wide character codes in the wide
character string, an additional property of the L""
approach may be
used. 16-bit characters may be entered using hexadecimal notation, in the
same way as C:
L"Wide characters: \x3042\x3043"
A new Lua library, located in lwstrlib.c, has been added for the new functionality. In most respects, it mirrors the ANSI string library, lstrlib.c.
LUA_TWSTRING
type added. Mirrors
LUA_TSTRING
.print()
has been upgraded to take Unicode strings as input.tonumber()
can take a Unicode string as a parameter.tostring()
receives a Unicode string as input, it converts it to ANSI
and returns it.towstring()
added. If
towstring()
receives an ANSI string as input,
it converts it to Unicode and returns it.fh:read()
can read Unicode files/strings if the input string is Unicode.
The file must be opened in binary mode.fh:write()
can write Unicode strings.lua_boxpointer() and lua_unboxpointer() have the unfortunate disadvantage of decoupling their behavior from the lua_touserdata() call. If you box a pointer, you have to unbox the pointer. In the past, a boxed pointer was retrievable through lua_touserdata.
To that end, an implementation of the old lua_newuserdatabox() is included in the LuaPlus distribution as LuaPlus::NewUserDataBox(). Its value is retrieves via LuaObject::GetUserData() (or lua_touserdata()).
This distribution replaces the #define
approach to memory allocation within Lua with a callback mechanism, where the memory allocators can be replaced on a
per Lua state basis. This allows a powerful mechanism to be employed to
adjust memory allocation strategies on a per state basis.
For purposes of better memory tracking, the realloc()
callback allows a void
pointer of user data, an allocation name, and allocation flags to be passed
along. All of these arguments are optional, but they are available if the
memory allocation callback needs them.
The only allocation flag available is LUA_ALLOC_TEMP
. A
memory manager could react to the LUA_ALLOC_TEMP
flag, for instance, by allocating
the code for the main function of a Lua file at the top of the heap. If
all other Lua allocations happen at the bottom of the heap, no holes will be
left in memory when the LUA_ALLOC_TEMP
flagged allocation is garbage collection.
The callbacks look like:
static void* luaHelper_ReallocFunction(void* ptr, int size, void* data, const char* allocName, unsigned int allocFlags) { return realloc(ptr, size); }
The allocation functions must be assigned before a Lua global state is
created, in a fashion similar to below. It is good practice to restore the
previous realloc()
callback.
lua_ReallocFunction oldReallocFunc; void* oldData; lua_getdefaultreallocfunction(&oldReallocFunc, &oldData); lua_setdefaultreallocfunctions(luaHelper_ReallocFunction, NULL); lua_State* state = lua_open(0); lua_setdefaultreallocfunctions(oldReallocFunc, oldData);
This section is out of date!
A whole host of functionality has been added to facilitate the optimization of memory usage in a tight memory environment.
lua_setminimumstringtablesize(int numstrings)
will ensure the
global string table is always of the minimum size specified by
numstrings
. When garbage
collection occurs, the string table will never shrink below
numstrings
.
An application can determine the maximum number of strings it will use and
ensure the space is reserved in advance, so as to avoid fragmentation when the
string table is resized.lua_setdefaulttagtablesize(int numtags)
will create a hash table of
numtags
size for the tag table.lua_setminimumglobaltablesize(int numentries)
ensures the globals table is
capable of at least holding numentries
elements without resizing
to avoid fragmenting the heap.lua_setminimumauxspace(int size)
creates a minimum auxiliary space buffer
of size
bytes. Auxiliary space is automatically allocated with
the allocation flag LUA_ALLOC_TEMP
. An application might
use this to put auxiliary space at the top of a heap or in some other
location, so later freeing of it doesn't cause fragmentation issues.lua_newtablesize(lua_State* L, int size)
is an enhanced version of
lua_newtable()
that creates a hash table of size so as to avoid reallocations.luaM_setname()
macro added and is used internally to name groups of
allocations. The name is passed into the realloc()
callback
function and may be used to better categorize allocations.lua_loadfile()
has been optimized to not push temporary strings to the Lua
stack which immediately can be garbage collected. This is another optimization that avoids
"holes" in a memory heap.table = { &100 1, 2, 3, 4, 5, 6 }
where the
&100
creates a
table hash table of size 100. The &100
may, of course, be any value.This section is out of date! Multithreading is NOT built into LuaPlus by default.
Multithreading is built into the LuaState distribution by default. The
function lua_setlockfunctions()
can be used to set up the multithreading.
Example:
static void LSLock(void* data) { CRITICAL_SECTION* cs = (CRITICAL_SECTION*)data; ::EnterCriticalSection(cs); } static void LSUnlock(void* data) { CRITICAL_SECTION* cs = (CRITICAL_SECTION*)data; ::LeaveCriticalSection(cs); } lua_State* m_state = lua_open(stackSize); CRITICAL_SECTION* cs = new CRITICAL_SECTION; ::InitializeCriticalSection(cs); lua_setlockfunctions(m_state, LSLock, LSUnlock, cs);
string.format
has been extended with the following control types. The use of
these control types makes it easy to write binary file formats to disk.
format("%bb", 255)
creates a string containing the 8-bit byte
255
.format("%bw", 1000)
creates a string containing the 16-bit word
1000
.format("%bd", 1000000)
creates a string containing the 32-bit dword
1000000
.format("%bf", 1.0f)
creates a string containing the 32-bit float
1.0
.format("%bF", 1.0)
creates a string containing the 64-bit double
1.0
.format("%Q", str)
turns a binary string into a printable string.Additionally, much like wide character string, ANSI strings can use the hexadecimal character notation to insert bytes into the string:
str = "Hel\x80o"
This section is out of date!
Basic type metatables are based heavily on Edgar Toernig's Sol implementation of unified methods.
In addition to standard Lua supporting metatables for tables and
userdata, a metatable per Lua's simple types (nil
,
boolean, number
,
string
, wstring
, and
function
) has been added. A string and
wstring, for instance, have indistinguishable len() functions.
str = "Hello" wstr = L"Hello" print(str:len()) print(wstr:len())
The default method tables have been put into global names for convenience.
They are named like the type but with a capital first letter (Nil
,
Number
,
String
, WString
,
Function
, Table
,
Userdata
).
Method tables may be accessed from within Lua using the
getmethodtable()
function.
mytable = {} -- Save the old methods. tableMethods = getmethodtable(mytable) newMethods = { doNothing = function(self) end } -- Set the new methods. setmethodtable(mytable, newMethods) mytable:doNothing()
In C, methods may be retrieved using the following functions:
LUA_API void lua_getmethods(lua_State *L, int index); LUA_API void lua_getdefaultmethods(lua_State *L, int type); LUA_API void lua_setmethods(lua_State *L, int index);
The LuaState distribution can write out a Lua table in a formatted file. The only downsides to LuaState's approach is that the table can't currently be cyclic and metatables aren't currently written.
A table can be written both from Lua and C++. The function prototypes are:
function LuaDumpObject(file, objectName, valueToWrite, alphabetical, indentLevel, maxIndentLevel, writeAll)
file
- The name of the file to write
to disk, a FILE* user data (say, from io.open()), or a "@" string for logging
to OutputDebugString.objectName
- The name of the initial Lua table to write to
disk.valueToWrite
- The Lua table to write.alphabetical
- If true, each table
written is sorted (optional: defaults to false).indentLevel
- The number of tabs to indent each line.
Passing in -1 will cause special formatting to occur that assumes the globals
table is being written. (optional: defaults to false)maxIndentLevel
- May be nil. The maximum number of
nested tables allowed in the write. If this value is exceeded, then no
carriage returns are inserted. (optional: defaults to false)writeAll
- If true, writes all Lua objects out, including
function and user data information. (optional: defaults to false)The C++ functionality is very similar in form.
Has a single function for retrieving the text from a clipboard.
clipboard.GetText()
Retrieves the text from the clipboard and returns it as a string.
Heavily based on the LuaCom 1.0 (beta) implementation by Vinicius Almendra and Renato Cerqueira. For the moment, the original LuaCom.pdf file is in the Docs/ directory. There are a whole bunch of samples in the Test/ directory showing how some of the facilities of the COM module are used.
com.CreateObject(progID)
com.GetActiveObject(progID)
com.SafeArray()
Glob is a file globbing (matching) facility described in detail at http://www.codeproject.com/file/fileglob.asp. The files found are returned in a table at completion.
table = glob.match("**")
Even though popen() is available under Windows, it is horribly broken, is only unidirectional, and only works for a command-line app. The pipe module provides a facility whereby applications may use pipe facilities without these limitations.
pipe.popen(commandLine)
Returns a table with entries for stdin, stdout, and stderr. These file handles work as if they were opened through the io library.
pipe.pclose(popenTable)
Immediately closes the stdin, stdout, and stderr pipes. Normally, these would just be garbage collected, but if the application needed them to be shut down early, pipe.pclose() is the way to do it.
pipe.lines(commandLine)
Similar to the io.lines() facility. Used in a for loop to simplify retrieving all the lines in a file (or in this case, pipe).
for line in pipe.lines("dir") do print(line) end
The windows module contains functions for manipulating the Microsoft Windows windowing system. Documentation will be forthcoming.
This section is out of date!
FileFind = { -- Returns a handle representing the first file matching fileName. function First(fileName) -- Retrieves the next file matching fileName. function Next(self) -- Closes the file search. function Close(self) -- Gets the file name of the currently matched file. function GetFileName(self) -- Determines if the currently matched file is a directory. function IsDirectory(self) } -- Added to File: io = { -- Returns the size of fileName. function GetFileSize(fileName) -- Returns as two numbers the last write time for fileName. function GetWriteTime(fileName) -- Sets the write time for fileName. function SetWriteTime(fileName, timeLo, timeHi) -- Same as the C function _access. function access(fileName, type) } -- Returns a new table with a hash table of size. function NewTableSize(size) -- Copies a non-cyclic table recursively. function CopyTable(tableToCopy) -- Looks up a table entry by string name: Table1.Table2.3.Value2 function FullLookup(table, lookupStr) -- Processes all the files matching wildcard in the directory [path] and calls func(path, name) on each one. function DirProcessFiles(path, wildcard, func) -- Recursively processes all the files in the directory [path], optionally matching [ext] and calls func(path, name) on each one. function DirProcessFilesRecursive(path, func, ext)