Lua Faq |
|
If you have a question about Lua, and haven't had any luck finding the answer in available resources, such as the Lua documentation and this FAQ, the best thing to do is post it to lua-l [2]. That will allow the most people to see it in the shortest time, and you are likely to get a timely response. If some experienced person on the list feels that your question is frequently asked, they may add an entry to this FAQ.
function() return ... end, are verbose
extern "C" block, required for C++, in the API header?
if statement:
if some_option then my_table = { ... } function foo() ... end else ... end
Some argue that this will still generate byte code, wasting CPU time and memory. Since conversion to byte code can always be done offline, the issue of CPU time can be easily resolved. Regarding memory, byte code size is often insignificant compared to dynamic memory usage. Nonetheless, a solution for avoiding unecessary byte code is to use the C preprocessor:
#if SOME_OPTION my_table = { ... } function foo() ... end #else ... #endif
For example, using gcc, the code above can be run like this:
gcc -E -P -DSOME_OPTION -x c test.lua | lua
__gc and __len metamethods work on tables?__gc metamethod for that purpose. However, this is not allowed on tables for efficiency.
Normally, there is no need to set a destructor on a table, since the table will be deleted automatically, and any references the table contains will then be garbage collected normally. A possible workaround is to create a userdata; make the table the userdata's environment table, and place a reference to the userdata in the table. (Make sure that this is the only reference to the userdata.) When the table becomes collectable, the userdata's __gc metamethod will be run; Lua will not actually destroy the table before that happens because the table is referenced by the userdata.
__len on tables is scheduled to be supported in 5.2. See LuaFiveTwo.
I thought the reason was more practical. Many argue for adding these operators because of the efficiency gains they enable. But in Lua things would get confusing because of the extension system. It's in the lua-l archives somewhere... --JohnBelmonte
See CountingFromOne.
function() return ... end, are verbose
See DetectingUndefinedVariables.
See BitwiseOperators.
Besides busy-waiting, the standard version of Lua does not have a built-in function for this since ANSI C does not support it. However, you can write your own "sleep" function in C and expose that funtion to Lua (or use someone else's library, like ExtensionProposal, that already does this). You may also be able to call os.execute on a process that sleeps, e.g. os.execute("sleep 5"), but this is operating system dependent (*nix) and creates a new process. See also LuaList:2008-03/msg00209.html .
read() and write() now must be accessed from a global table, for instance, as io.read() or io.write(). Other functions, such as readfrom(), no longer exist. (io.popen() can be used if supported by your platform.)
There were also a variety of syntactical changes; the %upvalue syntax no longer exists, since Lua has true lexical scoping since version 5.0; % is now the remainder operator.
The use of the special arg variable for vararg functions is deprecated, and will be removed from a future version. Vararg functions should be rewritten to use the new ... pseudo-value, but a short-term workaround is to start the function with:
function va(x, ...) local arg = { n=select('#', ...), ... } -- rest of function end
Since Lua 5.1, the abbreviated for k, v in tab syntax no longer works; it should be replaced by for k, v in pairs(tab).
Any code which used tagmethods will have to be rewritten to use metamethods instead.
In case of desperation, old versions of Lua continue to be available in source form from the Lua webpages.
Yes. See ObjectOrientationTutorial, SimpleLuaClasses, etc.
See the GUI section in LibrariesAndBindings.
Lua comes with debugger interface, so that users can write their own monitoring code (e.g., for a debugger, tracer, or profiler). For a sample debugger, see [ldb] by RiciLake, [RemDebug] in Kepler . There is also a much older [Ldb] by Tomás Guisasola and SimpleDebugger. You can also write your own through the Lua Debug library [5].
See ProfilerInLua, PepperfishProfiler, and LuaProfiler. You can also write your own through the Lua Debug library [5].
It means the error occurred inside a C/C++ function.
extern "C" the Lua header files since they are ANSI C headers. See the next FAQ and BuildingLua. For a more sophisticated solutions, see "Code wrappers" on LuaAddons.
luaL_checkstack()). Enable api checking while you are debugging. For Lua 5.1, compile with -DLUA_USE_APICHECK; see this message for Lua 5.0 instructions: [6]
As of Lua 5.0, this configuration is not supported; you may only have one instance of liblua in a given execution image.
The state initialization procedure changed between Lua 5.0 and Lua 5.1. It is now necessary to lua_call the various luaopen_* functions. Previously, these were simply called with a normal C call, but doing so now will cause a crash (or the above mentioned error) during the initialization of the io library.
The easiest way to initialize a lua_State is to use luaL_openlibs() which is defined in the file linit.c, or to copy the code from that file, modifying the list of libraries to initialize according to your needs.
extern "C" block, required for C++, in the API header?
extern "C" {
#include "lua.h"
}
Another reason is that Lua is also correct C++ code. You can compile Lua with a C++ compiler without any changes. If it had the extern "C" declaration, Lua would generate a C interface even when compiled as a C++ library. See BuildingLua.
The VM format is not publicly documented and is likely to change at the whim of the Lua developers. It isn't really recommended to try and write VM instructions directly.
I have a sneaking suspicion that someone (not a Lua developer) on the list wrote a document describing the VM instructions.
If you're interested in this kind of thing, you can use luac -l (luac is provided in the standard distribution) to see the VM instructions that Lua compiles a source into. It's also not too hard to poke about in the sources to Lua to see what is going on (see lvm.c in the standard distribution).
See LibraryGuidelines page
As the comment of the function _CrtIsValidHeapPointer says: "verify pointer is not only a valid pointer but also that it is from the 'local' heap. Pointers from another copy of the C runtime (even in the same process) will be caught."
Let's check the details of the 'invalid pointer'. When lua_open() return a lua_State* L, it's with a stack of default size 45. If you make some fault not clear the return values of function, that garbage will finally pile up on the stack and crash the stack memory block. When a new op needs to increase the stack size, a realloc will happen, and the CRT will find that the old pointer is invalid and this will lead a _CrtIsValidHeapPointer failure.
To fix, just carefully check your code (using lua_gettop(L) to check the stack size) and clean the unused slot on the stack.
For the 'non local heap' one, please check and make sure Lua lib doesn't have a separate copy of CRT.
More details can be found here:http://www.blogcn.com/User4/al_lea/blog/39582295.html
The POSIX.1 standard specifies that one must use pclose instead of fclose to close a FILE* created with popen. The IO library uses function environments to specify on a per-file basis which close function is to be used. luaopen_io sets its own function environment so that the iolib functions that don't specify otherwise implicitly use fclose.
If you were to call luaopen_io directly instead of with lua_call, it would set the calling C function's function environment. (Worse, if you're calling it from the "outside", there will not even be a calling C function, and bad stuff will happen.) Using lua_call saves that from happening.
Also, if you're writing a Lua library and you want to return an iolib file handle, it's not as easy as it could be. On top of getting and using the metatable for "FILE*", you have to specify a __close in the function environment of your userdata (or the function creating it).
For example:
/* when registering the C function that returns a file handle */ lua_pushcfunction(L, mycfunction); lua_newtable(L); lua_pushcfunction(L, myclose); lua_setfield(L, -2, "__close"); lua_setfenv(L, -2); /* when creating the actual filehandle */ FILE** p = (FILE**)lua_newuserdata(L, sizeof(FILE*)); luaL_getmetatable(L, "FILE*"); lua_setmetatable(L, -2); *p = myfile;
Use lua_next[7]. If the table is an array, you can instead call lua_gettable[8] or lua_rawgeti[9] in a loop that exits when nil is found or lua_objlen[10] is reached. In other cases, its more convenient to call a Lua function that iterates over the table.
You could try looking at the LuaComparison page for comparisons with other languages.
The main problem with embedding third-party code is that the host software (or the programmers) must sometimes adapt to fit around it. Lua adopts a number of strategies to prevent responsibilities from leaking between the embedded interpreter and the host program. If you have had previous experience with embedded interpreters, you might be inclined to ask some of the following questions.
The core source code of some projects relies heavily on OS-specific system calls. This situation is likely to occur when the software is developed primarily for a popular platform and then other platforms are supported via independent porting projects. Each porting project can follow its own agenda without worrying about the others. Conditional compilation (#ifdef, etc) is often used to provide separate code sequences for each supported platform.
This approach seems reasonable but the code may vary in quality among the platforms and the less popular ports may only appear months after each official release. If such code is embedded then the host program will only be able to run on the platforms supported by the embedded unit. If the host is to have identical features across all target platforms, then it may be necessary to delay development until all the ports are in alignment or else to use a less recent version of the unit.
Furthermore, some C source code uses non-standard features of a particular compiler. This is another common symptom of independent porting projects - each project can simply require developers to use the most popular compiler for their target platform. If an embedded unit depends on special features of compiler X then the host might also need to be compiled with compiler X. If, at this point, the host is already relying on different non-standard features of compiler Y then either the unit or the host might require heavy modification.
Lua avoids all these problems by sticking to the common subset of ANSI C and C++ in its source. This gives the interpreter the best possible chance of working with whatever compiler is already being used for the host. Additionally, Lua uses no OS-specific routines and the exact same code base builds correctly on all known platforms.
Some organisations operate code quality policies that require programmers to eliminate all compiler warnings as they go along. Under these conditions, an embedded unit can be a major problem if its code generates warnings. At best, it might be necessary to check the list of warnings during every compilation to ensure none of them originated from the host program. At worst, it might be necessary to modify all offending code in the unit. A modified unit is, of course, no longer consistent with the standard distribution and so the same modifications will likely have to be repeated each time a new version of the unit is released. (An open source project might allow the modifications to be commited back to the main codebase, but there is no guarantee that other developers will maintain the same level of discipline in the future.)
Lua is designed with this issue in mind. During testing, the source is compiled with the maximum level of warnings on a number of compilers. Any resulting warnings are eliminated before the code is released.
Internally, an embeddable unit of code may use complex and esoteric data structures, often for perfectly valid reasons. However, if the unit's API also relies on these structures then the embedder may be forced to spend time learning the unit's way of doing things. This so-called "impedance mismatch" is particularly likely when embedding a scripting language. Some interpreters require their initial state (global variables, etc) to be set up by the host using the interpreter's data structures. Also, it will usually be necessary for the host and the interpreter to exchange data values from time to time. Ideally, the host shouldn't be forced to use the interpreter's structures for its own data or else to perform troublesome conversions each time data is exchanged.
Lua has a simple API where the initial state is created without using any of the interpreter's internal structures. Furthermore, data is exchanged with the host via a simple stack which receives and produces values in their natural C datatype.
The flipside of this issue is that the interpreter could use simple, well-behaved types in its API, but then require the host to reduce its own esoteric data to these types for purposes of exchange. This also forces the host to use conversion routines or to represent its own data in simple, unstructured types throughout. Lua's answer is to allow so-called userdata types. These are blocks of memory that Lua does not "understand" directly but which it can manipulate via callbacks to the host. Thus the standard Lua operations can be made to work directly on the host's data as if it were native to the interpreter.
Lua uses its own automatic memory management which operates in a memory space of a fixed size determined by the host program. This means that no system calls will be needed to allocate memory during script execution. An interpreter can therefore be used in situations where such calls are unsafe.
However, automatic memory management can create problems in itself. Some garbage collection systems suffer from "pregnant pauses" where the main program freezes during collection cycles. Lua's incremental collection has the same time overheads as other techniques, but it spreads them evenly in small steps over the program's execution. Latency in such a system is very consistent, possibly even more so than in systems that use manual memory management. Furthermore, the time between collection steps and the time spent on each step can be controlled by the host on the fly. An embedded Lua can therefore be configured and tested for a specific latency requirement quite easily and should pass or fail tests cleanly during development rather than creating surprises after deployment.
For maximum flexibility, Lua can optionally store the host's userdata objects in its own memory space or let the host manage their memory explicitly. The host need not be wary of garbage collection for data it shares with the interpreter.
Lua code can be stored and loaded in a pre-compiled binary form which can be generated by its standard compiler tool, luac. The binary form is more memory-efficient than source text, but also allows another possibility for the interpreter: the parsing/compiling code can be removed altogether. This reduces the size of the already small Lua core to about 40K. Lua programs in binary form can also be encoded as C strings and easily stored in the host's source code. It is therefore convenient to use Lua in devices that lack a filesystem.