From 3afed43cdb435c788964d983a358d97ee291c2fc Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 5 Apr 2012 11:59:39 +0400 Subject: [PATCH] Experimental: try wrapping a dfhack api function. --- library/LuaTools.cpp | 6 ++++++ library/LuaTypes.cpp | 11 ++++++++--- library/LuaWrapper.cpp | 5 ++++- library/include/DataFuncs.h | 22 ++++++++++++++++++++-- library/include/LuaWrapper.h | 5 +++++ 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp index 5a50d0dd2..16c60457a 100644 --- a/library/LuaTools.cpp +++ b/library/LuaTools.cpp @@ -35,14 +35,18 @@ distribution. // must be last due to MS stupidity #include "DataDefs.h" #include "DataIdentity.h" +#include "DataFuncs.h" #include "modules/World.h" +#include "modules/Gui.h" #include "LuaWrapper.h" #include "LuaTools.h" #include "MiscUtils.h" +#include "df/job.h" + #include #include #include @@ -868,6 +872,8 @@ lua_State *DFHack::Lua::Open(color_ostream &out, lua_State *state) OpenPersistent(state); + LuaWrapper::AddMethodWrapper(state, 0, -1, "getSelectedJob", df::wrap_function(&Gui::getSelectedJob)); + lua_setglobal(state, "dfhack"); // load dfhack.lua diff --git a/library/LuaTypes.cpp b/library/LuaTypes.cpp index 6d5961f8d..2cc929ee9 100644 --- a/library/LuaTypes.cpp +++ b/library/LuaTypes.cpp @@ -1029,11 +1029,16 @@ static int meta_call_function(lua_State *state) /** * Create a closure invoking the given function, and add it to the field table. */ -static void AddMethodWrapper(lua_State *state, int meta_idx, int field_idx, - const char *name, function_identity_base *fun) +void LuaWrapper::AddMethodWrapper(lua_State *state, int meta_idx, int field_idx, + const char *name, function_identity_base *fun) { + field_idx = lua_absindex(state, field_idx); + lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN); - lua_pushvalue(state, meta_idx); + if (meta_idx) + lua_pushvalue(state, meta_idx); + else + lua_pushlightuserdata(state, NULL); // can't be a metatable lua_pushfstring(state, "%s()", name); lua_pushlightuserdata(state, fun); lua_pushcclosure(state, meta_call_function, 4); diff --git a/library/LuaWrapper.cpp b/library/LuaWrapper.cpp index 818e6b9e1..2f3958efe 100644 --- a/library/LuaWrapper.cpp +++ b/library/LuaWrapper.cpp @@ -53,7 +53,10 @@ static luaL_Reg no_functions[] = { { NULL, NULL } }; */ void LuaWrapper::field_error(lua_State *state, int index, const char *err, const char *mode) { - lua_getfield(state, UPVAL_METATABLE, "__metatable"); + if (lua_islightuserdata(state, UPVAL_METATABLE)) + lua_pushstring(state, "(global)"); + else + lua_getfield(state, UPVAL_METATABLE, "__metatable"); const char *cname = lua_tostring(state, -1); const char *fname = index ? lua_tostring(state, index) : "*"; luaL_error(state, "Cannot %s field %s.%s: %s.", diff --git a/library/include/DataFuncs.h b/library/include/DataFuncs.h index 109b2c176..3529d8059 100644 --- a/library/include/DataFuncs.h +++ b/library/include/DataFuncs.h @@ -67,10 +67,15 @@ namespace df { CT *self = (CT*)DFHack::LuaWrapper::get_object_addr(state, base++, UPVAL_METHOD_NAME, "invoke"); #define LOAD_ARG(type) \ type v##type; df::identity_traits::get()->lua_write(state, UPVAL_METHOD_NAME, &v##type, base++); +#define OSTREAM_ARG DFHack::color_ostream& +#define LOAD_OSTREAM(name) \ + DFHack::color_ostream_proxy name(DFHack::Core::getInstance().getConsole()); -#define INSTANTIATE_WRAPPERS(Count, FArgs, Args, Loads) \ +#define INSTANTIATE_RETURN_TYPE(FArgs) \ template struct return_type { typedef RT type; }; \ - template struct return_type { typedef RT type; }; \ + template struct return_type { typedef RT type; }; + +#define INSTANTIATE_WRAPPERS(Count, FArgs, Args, Loads) \ template struct function_wrapper { \ static const bool is_method = false; \ static const int num_args = Count; \ @@ -96,24 +101,35 @@ namespace df { #define FW_TARGSC #define FW_TARGS +INSTANTIATE_RETURN_TYPE(()) INSTANTIATE_WRAPPERS(0, (), (), ;) +INSTANTIATE_WRAPPERS(0, (OSTREAM_ARG), (out), LOAD_OSTREAM(out);) #undef FW_TARGS #undef FW_TARGSC #define FW_TARGSC FW_TARGS, #define FW_TARGS class A1 +INSTANTIATE_RETURN_TYPE((A1)) INSTANTIATE_WRAPPERS(1, (A1), (vA1), LOAD_ARG(A1);) +INSTANTIATE_WRAPPERS(1, (OSTREAM_ARG,A1), (out,vA1), LOAD_OSTREAM(out); LOAD_ARG(A1);) #undef FW_TARGS #define FW_TARGS class A1, class A2 +INSTANTIATE_RETURN_TYPE((A1,A2)) INSTANTIATE_WRAPPERS(2, (A1,A2), (vA1,vA2), LOAD_ARG(A1); LOAD_ARG(A2);) +INSTANTIATE_WRAPPERS(2, (OSTREAM_ARG,A1,A2), (out,vA1,vA2), + LOAD_OSTREAM(out); LOAD_ARG(A1); LOAD_ARG(A2);) #undef FW_TARGS #define FW_TARGS class A1, class A2, class A3 +INSTANTIATE_RETURN_TYPE((A1,A2,A3)) INSTANTIATE_WRAPPERS(3, (A1,A2,A3), (vA1,vA2,vA3), LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3);) +INSTANTIATE_WRAPPERS(3, (OSTREAM_ARG,A1,A2,A3), (out,vA1,vA2,vA3), + LOAD_OSTREAM(out); LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3);) #undef FW_TARGS #define FW_TARGS class A1, class A2, class A3, class A4 +INSTANTIATE_RETURN_TYPE((A1,A2,A3,A4)) INSTANTIATE_WRAPPERS(4, (A1,A2,A3,A4), (vA1,vA2,vA3,vA4), LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);) #undef FW_TARGS @@ -124,6 +140,8 @@ INSTANTIATE_WRAPPERS(4, (A1,A2,A3,A4), (vA1,vA2,vA3,vA4), #undef INVOKE_RV #undef LOAD_CLASS #undef LOAD_ARG +#undef OSTREAM_ARG +#undef LOAD_OSTREAM template class function_identity : public function_identity_base { diff --git a/library/include/LuaWrapper.h b/library/include/LuaWrapper.h index 72aa0e12e..66e77bb1f 100644 --- a/library/include/LuaWrapper.h +++ b/library/include/LuaWrapper.h @@ -220,6 +220,11 @@ namespace DFHack { namespace LuaWrapper { * and the enum itself to the _enum metafield. Pushes the key table on the stack. */ void AttachEnumKeys(lua_State *state, int meta_idx, int ftable_idx, type_identity *ienum); + /** + * Create a closure invoking the given function, and add it to the field table. + */ + void AddMethodWrapper(lua_State *state, int meta_idx, int field_idx, + const char *name, function_identity_base *fun); void IndexStatics(lua_State *state, int meta_idx, int ftable_idx, struct_identity *pstruct);