iLua modules are simply DLL files that export a single function used to populate the Lua state. By default, the function should be named
StartModule
, but the name can be overridden in the require
statement. The following function signature should be used:
extern "C" __declspec(dllexport) void StartModule(lua_State* L)
Modules need to dynamically link to Lua core library. The version currently used is 5.2.1, built with Visual Studio 2010. Additionally, a small set of header/source files is available to allow modules to interact with the core engine, as described below.
Since the engine tries to simulate multithreading, additional constraints are placed on C functions. All functions that can take a long
time to execute should suspend the Lua thread and return immediately, while doing the processing in a separate Windows thread. When finished,
the Lua thread should be resumed. The ilua::SlowOperation
class is provided to simplify this process.
When calling a Lua function from C, keep in mind that the engine might force it to yield. In this case, Lua will raise an error unless a continuation
function was specified in lua_callk
. This makes the design of such functions fairly complicated, see the source code for examples
(for example, re_sub
in core/api/regexp.cpp
).
ilua.h
contains Lua helper functions, functions for creating new data types, and core module interfaces. slowop.h
contains
a helper class for slow C functions. stream.h
defines a base class for data streams.
void luaL_printf(luaL_Buffer *B, const char *fmt, ...)
B
(see luaL_Buffer
).
void ilua::openlib(lua_State* L, char const* name)
name
on the stack.
void ilua::bindmethod(lua_State* L, char const* name, lua_CFunction func)
func
as field name
of the table on top of the stack. Equivalent to the following:
lua_pushcfunction(L, func); lua_setfield(L, -2, name);
void ilua::settabss(lua_State* L, char const* n, char const* s) void ilua::settabsi(lua_State* L, char const* n, int i) void ilua::settabsn(lua_State* L, char const* n) int ilua::gettabsi(lua_State* L, int idx, char const* n)
int ilua::ycall(lua_State* L, int args, int ret)
lua_callk
with continuation function that keeps
all results on the stack. Use in a return statement in case the function doesn't yield.
int ilua::checkoption(lua_State* L, int narg, const char* def, const char* const lst[])
luaL_checkoption
, but allows integer arguments.
template<class T> void newtype(lua_State* L, char const* name = NULL, char const* parent = NULL)
name
specifies type name; it is recommended to use lowercase names with periods to separate namespaces.
parent
optionally specifies the type to inherit from, this copies all parent methods to the new metatable.__index
table on the stack. The __newindex
metamethod points to a function that
creates a new metatable for the object to allow the caller to store additional fields in it (see ilua::totable
below).
bool ilua::iskindof(lua_State* L, char const* name, char const* base)
name
is a type equal to or derived from base
.
void* operator new(size_t count, lua_State* L, char const* name)
ilua::newtype<Foo>(L, "foo"); ... Foo* ptr = new(L, "foo") Foo(...);
template<class T> T* ilua::newstruct(lua_State* L, char const* name = NULL, size_t size = sizeof(T))
ilua::Object
.
Optionally, allows to allocate more space than the structure requires.
bool ilua::iskindof(lua_State* L, int pos, char const* name)
pos
is an object of type name
or of a derived type.
template<class T> bool ilua::iskindof(lua_State* L, int pos)
template<class T> T* ilua::toobject(lua_State* L, int pos, char const* name = NULL)
pos
if it is of the correct type, NULL
otherwise.
If name
is omitted, type is determined from the template argument.
template<class T> T* ilua::tostruct(lua_State* L, int pos)
template<class T> T* ilua::checkobject(lua_State* L, int pos, char const* name = NULL) template<class T> T* ilua::checkstruct(lua_State* L, int pos)
NULL
, a Lua error is generated.
int ilua::totable(lua_State* L, int pos)
class ilua::Object
Object
have the following additional functionality:
e
);ilua::pushobject
;Object
should only be constructed with the new
operator defined above.
int addref() int release() int refcount()
Object
. Objects that have non-zero reference count cannot
be garbage collected. Initial reference count is zero.
void ilua::pushobject(lua_State* L, Object* obj)
Object
.
class ilua::Engine
engine()
function.
ilua::Thread* load(char const* file)
NULL
. Errors will be displayed in the
editor.
bool load_module(char const* name, char const* entry = NULL)
"StartModule"
.
lua_State* lock() void unlock()
unlock
.
int get_counter(int id) void set_counter(int id, int value)
set_counter
,
and check if the counter is not zero before starting a new thread.
ID has to be a positive integer (not 0).
ilua::Thread* create_thread(int narg, int counter = 0)
create_thread
; narg
is the number of arguments pushed onto the stack. counter
can be set to a valid counter ID, see the previous functions for explanation.
ilua::Thread* current_thread()
NULL
can be returned while transitioning to a new thread, or when no threads are in the queue.
void keepalive()
keepalive
once will prevent the engine from terminating until exit
is called explicitly. There is no way to undo this
action.
void exit(int code)
ilua::Engine* ilua::engine(lua_State* L)
class ilua::Thread : public ilua::Object
lua_State* state()
Engine::lock/unlock
).
void suspend()
lua_yield
after calling suspend
.
void terminate()
lua_yield
.
int yield(lua_CFunction cont = NULL, int ctx = 0)
lua_yield
to pass execution to the next thread. Calling lua_yield
directly (without calling suspend
or terminate
first) will not re-queue the thread, which causes undefined behavior.
int sleep(int time, lua_CFunction cont = NULL, int ctx = 0)
yield
but waits the specified number of milliseconds before the thread is allowed to execute. Threads paused with this function
have a higher priority than normal threads.
void resume(Object* rc = NULL)
suspend
well be passed as arguments to the continuation function. If
rc
object is specified, it is also pushed onto the stack and added as an argument.
void lock() void unlock()
int id()
int status()
void* newdata(int size) void* data()
class ilua::SlowOperation
class BnIsPrime : public ilua::SlowOperation { bn::Number* num; int nchecks; public: BnIsPrime(bn::Number* a, int checks) : num(a), nchecks(checks) {} void run() { int isprime = bn::isprime(num, nchecks); lua_State* L = output_begin(); lua_pushboolean(L, isprime); output_end(1); } }; static int bn_isprime(lua_State* L) { bn::Number* a = bn_get(L, 1); int checks = luaL_optinteger(L, 2, 0); return (new(L) BnIsPrime(a, checks))->start(L); }We derive a class from
ilua::SlowOperation
that defines the run
method. Inside that method we perform the calculations,
and call output_begin
/output_end
to return the output to Lua (the engine is paused between these two calls). To run the
operation, we create an instance of our class with a custom allocator and call its start
method.
virtual void run() = 0
lua_State* output_begin() void output_end()
int start(lua_State* L)
void* operator new(size_t sz, lua_State* L)
class ilua::Stream : public ilua::Object
virtual char getc() virtual int putc(char c)
putc
should return the number of bytes written - that is, 0 or 1.
Default implementation calls read
/write
.
virtual int read(void* buf, int count) virtual int write(void const* buf, int count)
virtual void seek(int64 pos, int rel)
pos
specifies the offset from base position defined by rel
(SEEK_CUR
from current position, SEEK_SET
from beginning of file, SEEK_END
from end of file).
virtual int64 tell()
virtual int64 size()
virtual bool eof()
tell() >= size()
).
virtual void resize(int64 newsize)
virtual void flush()
unsigned short read16(bool big = false) unsigned long read32(bool big = false) float readfloat(bool big = false) double readdouble(bool big = false)
float
, or a 64-bit double
. Optionally reverses byte order.
void write16(unsigned short n, bool big = false) void write32(unsigned long n, bool big = false) void writefloat(float f, bool big = false) void writedouble(double f, bool big = false)
float
, or a 64-bit double
. Optionally reverses byte order.
int readstr(char* str, int size) void writestr(char const* str)
readstr
reads up to size
characters and returns the number of characters
read (not including the null terminator).
virtual int64 copy(Stream* stream, int64 count = 0)
count
bytes from stream
(specify 0 to copy all available bytes), equivalent to a combination of
read
/write
. Can be overridden to provide a faster implementation (e.g. read directly to stream memory).
void serialize(lua_State* L, int index) void deserialize(lua_State* L)
nil
, number, string, Lua function or a table containing listed
types. Supports recursive tables and metatables. Note that it does not check Lua functions for validity, do not use on untrusted data
(see Lua manual).
virtual const char* tolstring(size_t* len)
buffer
objects.
void stream_noseek(lua_State* L) void stream_noread(lua_State* L) void stream_nowrite(lua_State* L)
__index
table on top of the stack, for stream types
that do not support those operations.
int isbuffer(lua_State* L, int index)
stream
object or a string. Does not check if the stream supports the tolstring
operation.
char const* tobuffer(lua_State* L, int index, size_t* len) char const* checkbuffer(lua_State* L, int index, size_t* len) char const* optbuffer(lua_State* L, int index, char const* d, size_t* len)
tolstring
operation. Otherwise, call the default
lua_tostring
/luaL_checklstring
/luaL_optlstring
functions. Intended for functions that may want to
accept buffer objects in addition to strings.
void pushbuffer(lua_State* L, void const* data, size_t length)
data
and push it onto the stack. Initial position will be set to the beginning of stream.