Module Lua_api_lib
The Lua Application Program Interface (OCaml binding)
Difference with the original Lua API
Types definitions
type state
See lua_State documentation.
type oCamlFunction
= state -> int
This type corresponds to lua_CFunction. See lua_CFunction documentation.
type thread_status
=
|
LUA_OK
|
LUA_YIELD
|
LUA_ERRRUN
|
LUA_ERRSYNTAX
|
LUA_ERRMEM
|
LUA_ERRERR
|
LUA_ERRFILE
See lua_status documentation.
type gc_command
=
|
GCSTOP
|
GCRESTART
|
GCCOLLECT
|
GCCOUNT
|
GCCOUNTB
|
GCSTEP
|
GCSETPAUSE
|
GCSETSTEPMUL
This type is not present in the official API and is used by the function
gc
type lua_type
=
|
LUA_TNONE
|
LUA_TNIL
|
LUA_TBOOLEAN
|
LUA_TLIGHTUSERDATA
|
LUA_TNUMBER
|
LUA_TSTRING
|
LUA_TTABLE
|
LUA_TFUNCTION
|
LUA_TUSERDATA
|
LUA_TTHREAD
This type is a collection of the possible types of a Lua value, as defined by the macros in lua.h. As a reference, see the documentation of the lua_type function, and the corresponding OCaml
Lua_api_lib.type_
.
type 'a lua_Reader
= state -> 'a -> string option
See lua_Reader documentation.
type writer_status
=
|
NO_WRITING_ERROR
No errors, go on writing
|
WRITING_ERROR
An error occurred, stop writing
type 'a lua_Writer
= state -> string -> 'a -> writer_status
See lua_Writer documentation.
Constant values
val multret : int
Option for multiple returns in `Lua.pcall' and `Lua.call'. See lua_call documentation.
val registryindex : int
Pseudo-index to access the registry. See Registry documentation.
val environindex : int
Pseudo-index to access the environment of the running C function. See Registry documentation.
val globalsindex : int
Pseudo-index to access the thread environment (where global variables live). See Registry documentation.
Exceptions
exception
Error of thread_status
exception
Type_error of string
Functions not present in the Lua API
val thread_status_of_int : int -> thread_status
Convert an integer into a
thread_status
. Raisesfailure
on invalid parameter.
val int_of_thread_status : thread_status -> int
Convert a
thread_status
into an integer.
val lua_type_of_int : int -> lua_type
Convert an integer into a
lua_type
. Raisesfailure
on invalid parameter.
val int_of_lua_type : lua_type -> int
Convert a
lua_type
into an integer.
Lua API functions
val atpanic : state -> oCamlFunction -> oCamlFunction
See lua_atpanic documentation.
val checkstack : state -> int -> bool
See lua_checkstack documentation.
val concat : state -> int -> unit
See lua_concat documentation.
val cpcall : state -> oCamlFunction -> 'a -> thread_status
See lua_cpcall documentation.
NOTE: this function is not a binding of the original lua_cpcall, it's rather an OCaml function with the same semantics.
WARNING: the OCaml function you want to execute in a protected environment is actually protected againt Lua errors, even memory errors, but not against OCaml errors, i.e. exceptions. If for example you run:
let ls = LuaL.newstate ();; let my_func ls = failwith "Sorry, my fault..."; 0;; let cpcall_result = Lua.cpcall ls my_func 42;;
cpcall will actually raise a failure, because that exception is not generated by Lua but by OCaml.
val createtable : state -> int -> int -> unit
See lua_createtable documentation.
val dump : state -> 'a lua_Writer -> 'a -> writer_status
See lua_dump documentation.
val gc : state -> gc_command -> int -> int
See lua_gc documentation.
val getfenv : state -> int -> unit
See lua_getfenv documentation.
val getfield : state -> int -> string -> unit
See lua_getfield documentation.
val getglobal : state -> string -> unit
See lua_getglobal documentation. Like in the original Lua source code this function is implemented in OCaml using
getfield
.
val getmetatable : state -> int -> bool
See lua_getmetatable documentation.
val gettable : state -> int -> unit
See lua_gettable documentation.
val gettop : state -> int
See lua_gettop documentation.
val insert : state -> int -> unit
See lua_insert documentation.
val isboolean : state -> int -> bool
See lua_isboolean documentation.
val iscfunction : state -> int -> bool
See lua_iscfunction documentation.
val isfunction : state -> int -> bool
See lua_isfunction documentation.
val islightuserdata : state -> int -> bool
See lua_islightuserdata documentation.
val isnone : state -> int -> bool
See lua_isnone documentation.
val isnoneornil : state -> int -> bool
See lua_isnoneornil documentation.
val isnumber : state -> int -> bool
See lua_isnumber documentation.
val isstring : state -> int -> bool
See lua_isstring documentation.
val istable : state -> int -> bool
See lua_istable documentation.
val isthread : state -> int -> bool
See lua_isthread documentation.
val isuserdata : state -> int -> bool
See lua_isuserdata documentation.
val lessthan : state -> int -> int -> bool
See lua_lessthan documentation.
val load : state -> 'a lua_Reader -> 'a -> string -> thread_status
See lua_load documentation.
val newtable : state -> unit
See lua_newtable documentation.
val newthread : state -> state
See lua_newthread documentation.
When you create a new thread, this binding guaranties that the Lua object will remain "living" (protected from both the Lua and the OCaml garbage collectors) until a valid copy exists in at least one of the two contexts.
Remember that all the threads obtained by
newthread
andLua_api_lib.tothread
are shared copies, for example:let state = LuaL.newstate ();; let th = Lua.newthread state;; let th' = match Lua.tothread state 1 with Some s -> s | None -> failwith "not an option!";; Lua.settop state 0;;
Now the stack of
state
is empty and you have two threads,th
andth'
, but they are actually the very same data structure and operations performed on the first will be visible on the second!Another important issue regarding the scope of a state object representing a thread (coroutine): this binding don't prevent you from accessing invalid memory in case of misuse of the library. Please, carefully consider this fragment:
let f () = let state = LuaL.newstate () in let th = Lua.newthread state in th;; let th' = f ();; Gc.compact ();; (* This will collect [state] inside [f] *) (* Here something using [th'] *)
After
Gc.compact
the value insideth'
has lost any possible meaning, because it's a thread (a coroutine) of a state object that has been already collected. Usingth'
will lead to a segmentation fault, at best, and to an undefined behaviour if you are unlucky.
val default_gc : state -> int
This is the default "__gc" function attached to any new userdatum created with
newuserdata
. See documentation ofnewuserdata
below.
val make_gc_function : oCamlFunction -> oCamlFunction
This function takes an
oCamlFunction
you have created to be executed as "__gc" metamethod and "decorates" it with some default actions needed to deallocate all the memory.If you want to create a "__gc" method for your userdata, you must register the value from
make_gc_function
.
val newuserdata : state -> 'a -> unit
newuserdata
is the binding of lua_newuserdata but it works in a different way if compared to the original function, and the signature is slightly different.In C
lua_newuserdata
allocates an area for you, returns avoid*
and you cast it as needed. Moreover, it pushes the new userdata on the stack.In OCaml, however, you never allocates a value and so the resulting signature provides you a way to push an already created value on the top of the Lua stack.
Very important remark, read carefully. The original Lua
lua_newuserdata
doesn't associate to the new userdatum any metatable, it's up to you to define a metatable with metamethods, if you need it. On the other hand, this binding silently creates a metatable with only one metamethod ("__gc") and associates the functiondefault_gc
defined above. This function takes care of managing the memory between the two garbage collectors when needed. This is transparent to you, unless you want to attach to the userdatum a metatable of your, which is very likely to happen.In case you want to attach a metatable to your userdatum you must include the "__gc" metamethod, and you must create the function using
make_gc_function
described above.If you want a metatable for your userdatum but you don't need a "__gc", use in any case thedefault_gc
. Don't create a userdatum with a metatable and without "__gc" or your program will leak memory!WARNING: using this function could be harmful because it actually breaks the type system. It has the same semantics of
Obj.magic
, allowing the programmer to push an OCaml value into the Lua state, and then retrieve it with a different type. Be very careful!
val objlen : state -> int -> int
See lua_objlen documentation.
val pcall : state -> int -> int -> int -> thread_status
See lua_pcall documentation.
val pushboolean : state -> bool -> unit
See lua_pushboolean documentation.
val pushcfunction : state -> oCamlFunction -> unit
See lua_pushcfunction documentation.
val pushocamlfunction : state -> oCamlFunction -> unit
Alias of
Lua_api_lib.pushcfunction
val pushfstring : state -> ('a, unit, string, string) Stdlib.format4 -> 'a
Pushes onto the stack a formatted string and returns the string itself. It is similar to the standard library function sprintf.
Warning: this function has a different behavior with respect to the original lua_pushfstring because the conversion specifiers are not restricted as specified in the Lua documentation, but you can use all the conversions of the Printf module.
val pushinteger : state -> int -> unit
See lua_pushinteger documentation.
val pushlightuserdata : state -> 'a -> unit
See lua_pushlightuserdata documentation. Raises
Not_a_block_value
if you try to push a non-block value (e.g. an immediate integer) as a light userdata.In Lua a light userdata is a way to store inside the Lua state a C pointer. It's up the programmer to carefully check for the lifetime of the data structures passed to Lua via a light userdata. If you malloc a pointer and pass it to Lua, then you free it from C and then you retrieve the same pointer from Lua (using lua_touserdata), you are most probably shooting yourself in the foot.
To avoid this class of problems I decided to implement some logic in the binding of this function. When you push an OCaml value as a Lua light userdata, a global reference to that (OCaml) value is kept inside the Lua state L. So, if the original value goes out of scope it is not collected by the garbage collector. In this scenario:
let push_something state = let ocaml_value = get_some_complex_value () in pushlightuserdata state ocaml_value; state ;;
when the
push_something
function returns the Lua state, theocaml_value
is not collected and can be retrieved at a later time fromstate
.This behaviour has a major drawback: while ensuring the lifetime of objects, it wastes memory. All the OCaml values pushed as light userdata will in fact be collected when the garbage collector decide to collect the Lua state itself. This means that if you have a long running task (e.g. a server) with a Lua state and you use
pushlightuserdata
, the values pushed will be never collected!Moreover, if you push a value that have some resources associated with it (e.g. a channel, a socket or a DB handler) the resources will be released only when the Lua state goes out of scope.
val pushliteral : state -> string -> unit
See lua_pushliteral documentation.
val pushlstring : state -> string -> unit
See lua_pushlstring documentation.
val pushnil : state -> unit
See lua_pushnil documentation.
val pushnumber : state -> float -> unit
See lua_pushnumber documentation.
val pushstring : state -> string -> unit
See lua_pushstring documentation.
val pushthread : state -> bool
See lua_pushthread documentation.
val pushvalue : state -> int -> unit
See lua_pushvalue documentation.
val pushvfstring : state -> ('a, unit, string, string) Stdlib.format4 -> 'a
Alias of
Lua_api_lib.pushfstring
val rawequal : state -> int -> int -> bool
See lua_rawequal documentation.
val rawget : state -> int -> unit
See lua_rawget documentation.
val rawgeti : state -> int -> int -> unit
See lua_rawgeti documentation.
val rawset : state -> int -> unit
See lua_rawset documentation.
val rawseti : state -> int -> int -> unit
See lua_rawseti documentation.
val register : state -> string -> oCamlFunction -> unit
See lua_register documentation. The function is implemented in OCaml using pushcfunction and setglobal.
val remove : state -> int -> unit
See lua_remove documentation.
val replace : state -> int -> unit
See lua_replace documentation.
val resume : state -> int -> thread_status
See lua_resume documentation.
val setfenv : state -> int -> bool
See lua_setfenv documentation.
val setfield : state -> int -> string -> unit
See lua_setfield documentation.
val setglobal : state -> string -> unit
See lua_setglobal documentation.
val setmetatable : state -> int -> int
See lua_setmetatable documentation.
val settable : state -> int -> unit
See lua_settable documentation.
val settop : state -> int -> unit
See lua_settop documentation.
val status : state -> thread_status
See lua_status documentation.
val toboolean : state -> int -> bool
See lua_toboolean documentation.
val tocfunction : state -> int -> oCamlFunction option
See lua_tocfunction documentation.
val toocamlfunction : state -> int -> oCamlFunction option
Alias of
Lua_api_lib.tocfunction
val tointeger : state -> int -> int
See lua_tointeger documentation.
val tolstring : state -> int -> string option
See lua_tolstring documentation.
NOTE: The original
len
argument is missing because, unlike in C, there is no impedance mismatch between OCaml and Lua strings
val tonumber : state -> int -> float
See lua_tonumber documentation.
val tostring : state -> int -> string option
Alias of
Lua_api_lib.tolstring
val tothread : state -> int -> state option
See lua_tothread documentation.
val touserdata : state -> int -> [> `Userdata of 'a | `Light_userdata of 'a ] option
If the value at the given acceptable index is a full userdata, returns its value as
Some `Userdata v
. If the value is a light userdata, returns its value asSome `Light_userdata v
. Otherwise, returnsNone
.WARNING: using this function could be harmful because it actually breaks the type system. It has the same semantics of
Obj.magic
, allowing the programmer to push an OCaml value into the Lua state, and then retrieve it with a different type. Be very careful!
val typename : state -> lua_type -> string
See lua_typename documentation.