Thread overview | ||||||
---|---|---|---|---|---|---|
|
August 03, 2013 Started to work on a Lua wrapper. Please provide feedback & guidance | ||||
---|---|---|---|---|
| ||||
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"); } |
August 03, 2013 Re: Started to work on a Lua wrapper. Please provide feedback & guidance | ||||
---|---|---|---|---|
| ||||
Posted in reply to Gabi | On Saturday, 3 August 2013 at 22:17:32 UTC, Gabi wrote: > 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"); > } 2 projects you might be interested in with regards to D and Lua: Quite comprehensive, no Lua 5.2 yet though. https://github.com/JakobOvrum/LuaD Lua bindings, amongst other good stuff: https://github.com/aldacron/Derelict3 |
August 05, 2013 Re: Started to work on a Lua wrapper. Please provide feedback & guidance | ||||
---|---|---|---|---|
| ||||
Posted in reply to Gabi | On Saturday, 3 August 2013 at 22:17:32 UTC, Gabi wrote: > 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.. You'll probably like the LuaD wrapper https://github.com/JakobOvrum/LuaD It uses 5.1, but may be usable with 5.2 or simple to get the basics working. There is currently a bug open: https://github.com/JakobOvrum/LuaD/issues/19 So if you get it working for yourself, contributing back would be good. |
August 05, 2013 Re: Started to work on a Lua wrapper. Please provide feedback & guidance | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | On Monday, 5 August 2013 at 19:14:25 UTC, Jesse Phillips wrote:
> On Saturday, 3 August 2013 at 22:17:32 UTC, Gabi wrote:
>> 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..
>
> You'll probably like the LuaD wrapper
>
> https://github.com/JakobOvrum/LuaD
>
> It uses 5.1, but may be usable with 5.2 or simple to get the basics working. There is currently a bug open:
>
> https://github.com/JakobOvrum/LuaD/issues/19
>
> So if you get it working for yourself, contributing back would be good.
Right! I like this approach. That what I tried to achieve in my
Lua class above.
Will be happy to contribute if I can
|
Copyright © 1999-2021 by the D Language Foundation