Started to work on a Lua wrapper. Please provide feedback & guidance
Gabi
galim120 at bezeqint.net
Sat Aug 3 15:17:31 PDT 2013
I need a Lua 5.2.2 wrapper, So I started working on one..
I am new to D so probably there is a lot of room for
improvements..
Any feedback is welcome..
import std.stdio:writeln, writefln;
import std.exception:enforce;
import std.conv;
import std.string;
alias void lua_State;
alias long lua_Integer;
alias double lua_Number;
enum LUA_OK = 0;
enum LUA_MULTRET = -1;
extern (C)
{
lua_State *luaL_newstate ();
void lua_close (lua_State *L);
void luaL_openlibs (lua_State *L);
int lua_gettop (lua_State *L);
void lua_settop (lua_State *L, int index);
int luaL_loadstring (lua_State *L, const char *s);
int lua_pcallk (lua_State *L, int nargs, int nresults, int
errfunc, int ctx, void*);
void lua_setglobal (lua_State *L, const char *name);
void lua_getglobal (lua_State *L, const char *name);
void lua_getfield (lua_State *L, int index, const char *k);
lua_Number lua_tonumberx (lua_State *L, int index, int
*isnum);
lua_Integer lua_tointegerx (lua_State *L, int index, int
*isnum);
const char *lua_tolstring (lua_State *L, int index, size_t
*len);
const char *lua_pushstring (lua_State *L, const char *s);
void lua_pushinteger (lua_State *L, lua_Integer n);
void lua_pushnumber (lua_State *L, lua_Number n);
}
class LuaException:Exception
{
this (string msg)
{
super(msg);
}
}
class Lua
{
private:
lua_State* _luaState;
void _pushArg(long arg)
{
lua_pushinteger(_luaState, arg);
}
void _pushArg(int arg)
{
lua_pushinteger(_luaState, to!long(arg));
}
void _pushArg(double arg)
{
lua_pushnumber(_luaState, arg);
}
void _pushArg(float arg)
{
lua_pushnumber(_luaState, to!double(arg));
}
void _pushArg(string arg)
{
lua_pushstring(_luaState, arg.ptr);
}
void _pushArg(const char* arg)
{
lua_pushstring(_luaState, arg);
}
void _runFun(ARGS...)(string packageName, string funName,
ARGS args)
{
if(packageName.length == 0 || packageName == ".")
{
lua_getglobal(_luaState, funName.ptr);
}
else
{
lua_getglobal(_luaState, packageName.ptr);
lua_getfield(_luaState, -1, funName.ptr);
}
//Push arguments
foreach(arg; args)
{
_pushArg(arg);
}
int rv = lua_pcallk(_luaState, cast(int)args.length, 1,
0, 0, null );
enforce(rv == LUA_OK, new LuaException("runFun:lua_pcallk
failed"));
}
public:
this()
{
_luaState = luaL_newstate();
enforce(_luaState != null, new
LuaException("luaL_newstate() failed"));
luaL_openlibs(_luaState);
}
~this()
{
close();
}
void close()
{
if(_luaState != null)
lua_close(_luaState);
}
@property
lua_State* luaState()
{
return _luaState;
}
/*
* Load function
* Throw LuaException on error
*/
void loadFun(string funBody)
{
int rv = luaL_loadstring(_luaState, funBody.ptr);
enforce(rv == LUA_OK, new
LuaException("loadFun:luaL_loadstring failed"));
rv = lua_pcallk(_luaState, 0, LUA_MULTRET, 0, 0, null);
enforce(rv == LUA_OK, new
LuaException("loadFun:lua_pcallk failed"));
}
/*
* Load function and give it a name.
* funBody should be anonymous function like
"function(x,y)..end"
* Throw LuaException on error
*/
void loadFun(string funName, string funBody)
{
loadFun(funName ~ "=" ~funBody);
}
/*
* Execute the given function and return it rv
* packageName can be empty or "." for global scope function
* Throw LuaException on error
*/
T runFun(T:double, ARGS...)(string packageName, string
funName, ARGS args)
{
int top = lua_gettop(_luaState);
_runFun(packageName, funName, args);
scope(exit) lua_settop(_luaState, top);
return lua_tonumberx(_luaState, -1, null);
}
T runFun(T:long, ARGS...)(string packageName, string funName,
ARGS args)
{
int top = lua_gettop(_luaState);
_runFun(packageName, funName, args);
scope(exit) lua_settop(_luaState, top);
return lua_tointegerx(_luaState, -1, null);
}
T runFun(T:string, ARGS...)(string packageName, string
funName, ARGS args)
{
int top = lua_gettop(_luaState);
scope(exit) lua_settop(_luaState, top);
_runFun(packageName, funName, args);
const char* rv = lua_tolstring(_luaState, -1, null);
return to!string(rv);
}
T runFun(T:const char*, ARGS...)(string packageName, string
funName, ARGS args)
{
int top = lua_gettop(_luaState);
scope(exit) lua_settop(_luaState, top);
_runFun(packageName, funName, args);
return lua_tolstring(_luaState, -1, null);
}
}
unittest
{
string fn1 =
"""
function add(x, y)
return (x+y)
end
""";
string fn2 =
"""
function (x, y)
return (x..y)
end
""";
Lua l = new Lua();
l.loadFun(fn1);
assert(l.runFun!double(".", "add", 6, 3) == 9);
assert(l.runFun!long(".", "add", 3, -3) == 0L);
l.loadFun("concat", fn2);
assert(l.runFun!(string)(".", "concat", "AAA", "BBB") ==
"AAABBB");
}
More information about the Digitalmars-d-learn
mailing list