From 75cffcb34720b7d0950afa26e09dd1cc6b110b4b Mon Sep 17 00:00:00 2001 From: Warmist Date: Sat, 16 Jul 2011 17:22:45 +0300 Subject: [PATCH 1/8] First dfusion plugin commit Signed-off-by: Warmist --- plugins/CMakeLists.txt | 1 + plugins/Dfusion/CMakeLists.txt | 100 +++++++++++++++++++++++++++++++++ plugins/Dfusion/dfusion.cpp | 52 +++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 plugins/Dfusion/CMakeLists.txt create mode 100644 plugins/Dfusion/dfusion.cpp diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 5847f3b6f..f9d32044f 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -97,6 +97,7 @@ ENDMACRO(DFHACK_PLUGIN) #RECURSE_DIRS() add_subdirectory (qtplug) +add_subdirectory (dfusion) DFHACK_PLUGIN(reveal reveal.cpp) OPTION(BUILD_KITTENS "Build the kittens plugin." OFF) diff --git a/plugins/Dfusion/CMakeLists.txt b/plugins/Dfusion/CMakeLists.txt new file mode 100644 index 000000000..b38a2e221 --- /dev/null +++ b/plugins/Dfusion/CMakeLists.txt @@ -0,0 +1,100 @@ +#FIXME: inherit all macros and stuff from the dfhack SDK +IF(UNIX) + add_definitions(-DLINUX_BUILD) + SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall") + SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32") + SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32") +ENDIF() + +include_directories("${dfhack_SOURCE_DIR}/library/include") +MACRO(CAR var) + SET(${var} ${ARGV1}) +ENDMACRO(CAR) + +MACRO(CDR var junk) + SET(${var} ${ARGN}) +ENDMACRO(CDR) + +MACRO(LIST_CONTAINS var value) + SET(${var}) + FOREACH (value2 ${ARGN}) + IF (${value} STREQUAL ${value2}) + SET(${var} TRUE) + ENDIF (${value} STREQUAL ${value2}) + ENDFOREACH (value2) +ENDMACRO(LIST_CONTAINS) + +MACRO(PARSE_ARGUMENTS prefix arg_names option_names) + SET(DEFAULT_ARGS) + FOREACH(arg_name ${arg_names}) + SET(${prefix}_${arg_name}) + ENDFOREACH(arg_name) + FOREACH(option ${option_names}) + SET(${prefix}_${option} FALSE) + ENDFOREACH(option) + + SET(current_arg_name DEFAULT_ARGS) + SET(current_arg_list) + FOREACH(arg ${ARGN}) + LIST_CONTAINS(is_arg_name ${arg} ${arg_names}) + IF (is_arg_name) + SET(${prefix}_${current_arg_name} ${current_arg_list}) + SET(current_arg_name ${arg}) + SET(current_arg_list) + ELSE (is_arg_name) + LIST_CONTAINS(is_option ${arg} ${option_names}) + IF (is_option) + SET(${prefix}_${arg} TRUE) + ELSE (is_option) + SET(current_arg_list ${current_arg_list} ${arg}) + ENDIF (is_option) + ENDIF (is_arg_name) + ENDFOREACH(arg) + SET(${prefix}_${current_arg_name} ${current_arg_list}) +ENDMACRO(PARSE_ARGUMENTS) + +MACRO(DFHACK_PLUGIN) + PARSE_ARGUMENTS(PLUGIN + "LINK_LIBRARIES;DEPENDS" + "SOME_OPT" + ${ARGN} + ) + CAR(PLUGIN_NAME ${PLUGIN_DEFAULT_ARGS}) + CDR(PLUGIN_SOURCES ${PLUGIN_DEFAULT_ARGS}) + + ADD_LIBRARY(${PLUGIN_NAME} MODULE ${PLUGIN_SOURCES}) + TARGET_LINK_LIBRARIES(${PLUGIN_NAME} dfhack ${PLUGIN_LINK_LIBRARIES}) + IF(UNIX) + SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES SUFFIX .plug.so PREFIX "") + ELSE() + SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES SUFFIX .plug.dll) + ENDIF() + SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELEASE ${DFHACK_PLUGIN_OUTPUT_DIR}) + SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${DFHACK_PLUGIN_OUTPUT_DIR}) + SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${DFHACK_PLUGIN_OUTPUT_DIR}) + install(TARGETS ${PLUGIN_NAME} + LIBRARY DESTINATION ${DFHACK_PLUGIN_DESTINATION} + RUNTIME DESTINATION ${DFHACK_PLUGIN_DESTINATION}) + #MESSAGE("Depends: ${PLUGIN_DEPENDS}") + #IF (PLUGIN_AUTO_INSTALL) + # MESSAGE("Auto install") + #ENDIF (PLUGIN_AUTO_INSTALL) + #IF (PLUGIN_NO_MODULE) + # MESSAGE("No module") + #ENDIF (PLUGIN_NO_MODULE) +ENDMACRO(DFHACK_PLUGIN) + +# add all subdirectories. can be used in those subdirectories, etc... +# needs a re-run of cmake to pick up the changes +#macro(RECURSE_DIRS) +# file(GLOB sub-dir RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *) +# foreach(dir ${sub-dir}) +# if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${dir}) +# add_subdirectory (${dir}) +# endif() +# endforeach() +#endmacro() + +#RECURSE_DIRS() +DFHACK_PLUGIN(dfusion dfusion.cpp) + diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp new file mode 100644 index 000000000..38d25b88d --- /dev/null +++ b/plugins/Dfusion/dfusion.cpp @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include + + +using std::vector; +using std::string; +using namespace DFHack; + + +DFhackCExport command_result dfusion (Core * c, vector & parameters); + + +DFhackCExport const char * plugin_name ( void ) +{ + return "dfusion"; +} + +DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) +{ + commands.clear(); + commands.push_back(PluginCommand("DFusion","Init dfusion system.",dfusion)); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ +// shutdown stuff + return CR_OK; +} + +DFhackCExport command_result plugin_onupdate ( Core * c ) +{ + /*if(timering == true) + { + uint64_t time2 = GetTimeMs64(); + uint64_t delta = time2-timeLast; + timeLast = time2; + c->con.print("Time delta = %d ms\n", delta); + } + return CR_OK;*/ + return CR_OK; +} + +DFhackCExport command_result dfusion (Core * c, vector & parameters) +{ + // do stuff + return CR_OK; +} From 7969a701c3ba0495bc2a9e6870a7ce4d62002f4e Mon Sep 17 00:00:00 2001 From: Warmist Date: Sat, 16 Jul 2011 18:34:24 +0300 Subject: [PATCH 2/8] Lua integrated. Signed-off-by: Warmist --- plugins/Dfusion/CMakeLists.txt | 108 +++------------------------------ plugins/Dfusion/dfusion.cpp | 12 +++- 2 files changed, 20 insertions(+), 100 deletions(-) diff --git a/plugins/Dfusion/CMakeLists.txt b/plugins/Dfusion/CMakeLists.txt index b38a2e221..ba4d356d9 100644 --- a/plugins/Dfusion/CMakeLists.txt +++ b/plugins/Dfusion/CMakeLists.txt @@ -1,100 +1,10 @@ #FIXME: inherit all macros and stuff from the dfhack SDK -IF(UNIX) - add_definitions(-DLINUX_BUILD) - SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall") - SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -m32") - SET(CMAKE_C_FLAGS "-fvisibility=hidden -m32") -ENDIF() - -include_directories("${dfhack_SOURCE_DIR}/library/include") -MACRO(CAR var) - SET(${var} ${ARGV1}) -ENDMACRO(CAR) - -MACRO(CDR var junk) - SET(${var} ${ARGN}) -ENDMACRO(CDR) - -MACRO(LIST_CONTAINS var value) - SET(${var}) - FOREACH (value2 ${ARGN}) - IF (${value} STREQUAL ${value2}) - SET(${var} TRUE) - ENDIF (${value} STREQUAL ${value2}) - ENDFOREACH (value2) -ENDMACRO(LIST_CONTAINS) - -MACRO(PARSE_ARGUMENTS prefix arg_names option_names) - SET(DEFAULT_ARGS) - FOREACH(arg_name ${arg_names}) - SET(${prefix}_${arg_name}) - ENDFOREACH(arg_name) - FOREACH(option ${option_names}) - SET(${prefix}_${option} FALSE) - ENDFOREACH(option) - - SET(current_arg_name DEFAULT_ARGS) - SET(current_arg_list) - FOREACH(arg ${ARGN}) - LIST_CONTAINS(is_arg_name ${arg} ${arg_names}) - IF (is_arg_name) - SET(${prefix}_${current_arg_name} ${current_arg_list}) - SET(current_arg_name ${arg}) - SET(current_arg_list) - ELSE (is_arg_name) - LIST_CONTAINS(is_option ${arg} ${option_names}) - IF (is_option) - SET(${prefix}_${arg} TRUE) - ELSE (is_option) - SET(current_arg_list ${current_arg_list} ${arg}) - ENDIF (is_option) - ENDIF (is_arg_name) - ENDFOREACH(arg) - SET(${prefix}_${current_arg_name} ${current_arg_list}) -ENDMACRO(PARSE_ARGUMENTS) - -MACRO(DFHACK_PLUGIN) - PARSE_ARGUMENTS(PLUGIN - "LINK_LIBRARIES;DEPENDS" - "SOME_OPT" - ${ARGN} - ) - CAR(PLUGIN_NAME ${PLUGIN_DEFAULT_ARGS}) - CDR(PLUGIN_SOURCES ${PLUGIN_DEFAULT_ARGS}) - - ADD_LIBRARY(${PLUGIN_NAME} MODULE ${PLUGIN_SOURCES}) - TARGET_LINK_LIBRARIES(${PLUGIN_NAME} dfhack ${PLUGIN_LINK_LIBRARIES}) - IF(UNIX) - SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES SUFFIX .plug.so PREFIX "") - ELSE() - SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES SUFFIX .plug.dll) - ENDIF() - SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELEASE ${DFHACK_PLUGIN_OUTPUT_DIR}) - SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${DFHACK_PLUGIN_OUTPUT_DIR}) - SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${DFHACK_PLUGIN_OUTPUT_DIR}) - install(TARGETS ${PLUGIN_NAME} - LIBRARY DESTINATION ${DFHACK_PLUGIN_DESTINATION} - RUNTIME DESTINATION ${DFHACK_PLUGIN_DESTINATION}) - #MESSAGE("Depends: ${PLUGIN_DEPENDS}") - #IF (PLUGIN_AUTO_INSTALL) - # MESSAGE("Auto install") - #ENDIF (PLUGIN_AUTO_INSTALL) - #IF (PLUGIN_NO_MODULE) - # MESSAGE("No module") - #ENDIF (PLUGIN_NO_MODULE) -ENDMACRO(DFHACK_PLUGIN) - -# add all subdirectories. can be used in those subdirectories, etc... -# needs a re-run of cmake to pick up the changes -#macro(RECURSE_DIRS) -# file(GLOB sub-dir RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *) -# foreach(dir ${sub-dir}) -# if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${dir}) -# add_subdirectory (${dir}) -# endif() -# endforeach() -#endmacro() - -#RECURSE_DIRS() -DFHACK_PLUGIN(dfusion dfusion.cpp) - +find_package(Lua51 QUIET) +if(LUA51_FOUND) + include_directories(${LUA_INCLUDE_DIR}) + + DFHACK_PLUGIN(dfusion dfusion.cpp) + target_link_libraries(dfusion ${LUA_LIBRARIES}) +else(LUA51_FOUND) + MESSAGE(STATUS "Required libraries (lua51) not found - dfusion plugin can't be built.") +endif(LUA51_FOUND) diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index 38d25b88d..8f5f66edd 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -5,12 +5,13 @@ #include #include +#include using std::vector; using std::string; using namespace DFHack; - +lua_State *st; DFhackCExport command_result dfusion (Core * c, vector & parameters); @@ -23,6 +24,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector { commands.clear(); commands.push_back(PluginCommand("DFusion","Init dfusion system.",dfusion)); + st=luaL_newstate(); return CR_OK; } @@ -45,8 +47,16 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) return CR_OK; } + DFhackCExport command_result dfusion (Core * c, vector & parameters) { // do stuff + + Console &con=c->con; + + con.print("Hello world!"); + luaL_dostring(st,parameters[0].c_str()); + const char* p=luaL_checkstring(st,1); + con.print("ret=%s",p); return CR_OK; } From 3afa35df61e7b12e1cf2a50e14c0cc8d944992ce Mon Sep 17 00:00:00 2001 From: Warmist Date: Sat, 16 Jul 2011 19:29:46 +0300 Subject: [PATCH 3/8] Added lua c++ wrapper Signed-off-by: Warmist --- plugins/Dfusion/CMakeLists.txt | 13 +- plugins/Dfusion/dfusion.cpp | 22 +- plugins/Dfusion/include/luamain.h | 38 ++ plugins/Dfusion/include/luaxx.hpp | 525 +++++++++++++++++++ plugins/Dfusion/src/luamain.cpp | 69 +++ plugins/Dfusion/src/luaxx.cc | 824 ++++++++++++++++++++++++++++++ 6 files changed, 1480 insertions(+), 11 deletions(-) create mode 100644 plugins/Dfusion/include/luamain.h create mode 100644 plugins/Dfusion/include/luaxx.hpp create mode 100644 plugins/Dfusion/src/luamain.cpp create mode 100644 plugins/Dfusion/src/luaxx.cc diff --git a/plugins/Dfusion/CMakeLists.txt b/plugins/Dfusion/CMakeLists.txt index ba4d356d9..74527acb6 100644 --- a/plugins/Dfusion/CMakeLists.txt +++ b/plugins/Dfusion/CMakeLists.txt @@ -1,9 +1,14 @@ -#FIXME: inherit all macros and stuff from the dfhack SDK find_package(Lua51 QUIET) + if(LUA51_FOUND) - include_directories(${LUA_INCLUDE_DIR}) - - DFHACK_PLUGIN(dfusion dfusion.cpp) + include_directories(${LUA_INCLUDE_DIR} include) + FILE(GLOB DFUSION_CPPS src/*.c*) + set( + DFUSION_CPPS_ALL + dfusion.cpp + ${DFUSION_CPPS} + ) + DFHACK_PLUGIN(dfusion ${DFUSION_CPPS_ALL}) target_link_libraries(dfusion ${LUA_LIBRARIES}) else(LUA51_FOUND) MESSAGE(STATUS "Required libraries (lua51) not found - dfusion plugin can't be built.") diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index 8f5f66edd..d11d6c111 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -7,11 +7,14 @@ #include +#include + using std::vector; using std::string; using namespace DFHack; -lua_State *st; + + DFhackCExport command_result dfusion (Core * c, vector & parameters); @@ -24,12 +27,13 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector { commands.clear(); commands.push_back(PluginCommand("DFusion","Init dfusion system.",dfusion)); - st=luaL_newstate(); + return CR_OK; } DFhackCExport command_result plugin_shutdown ( Core * c ) { + // shutdown stuff return CR_OK; } @@ -51,12 +55,16 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result dfusion (Core * c, vector & parameters) { // do stuff - Console &con=c->con; - con.print("Hello world!"); - luaL_dostring(st,parameters[0].c_str()); - const char* p=luaL_checkstring(st,1); - con.print("ret=%s",p); + try{ + lua::glua::Get().loadfile("dfusion/init.lua"); + lua::glua::Get().pcall(0,0); + } + catch(lua::exception &e) + { + con.printerr("Error:%s",e.what()); + } + return CR_OK; } diff --git a/plugins/Dfusion/include/luamain.h b/plugins/Dfusion/include/luamain.h new file mode 100644 index 000000000..55c780582 --- /dev/null +++ b/plugins/Dfusion/include/luamain.h @@ -0,0 +1,38 @@ +#ifndef LUASTUFF_H +#define LUASTUFF_H +#include +using std::string; + +extern "C" { +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +} + +//#include "lune.h" +#include "luaxx.hpp" + +namespace lua +{ + //global lua state singleton + class glua + { + public: + static state &Get(); + private: + glua(); + static glua *ptr; + state mystate; + }; + //registers basic lua commands + void RegBasics(lua::state &L); + //dumps lua function trace, useless unless called from lua. + string DebugDump(lua::state &L); + //register functions, first registers into global scope, second into current table + void RegFunctions(lua::state &L,luaL_reg const *arr); + void RegFunctionsLocal(lua::state &L,luaL_reg const *arr); +} + + + +#endif // LUASTUFF_H diff --git a/plugins/Dfusion/include/luaxx.hpp b/plugins/Dfusion/include/luaxx.hpp new file mode 100644 index 000000000..f1873949b --- /dev/null +++ b/plugins/Dfusion/include/luaxx.hpp @@ -0,0 +1,525 @@ +/* vim: set et sw=3 tw=0 fo=croqlaw cino=t0: + * + * Luaxx, the C++ Lua wrapper library. + * Copyright (c) 2006-2008 Matthew Nicholson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef LUAXX_H +#define LUAXX_H + +#define lua_Integer_long 1 +#define lua_Integer_int 1 + +#include +#include +#include +#include +#include + +/** @file + * Luaxx header file. + */ + +/** @mainpage Luaxx + * + * Luaxx is a thin wrapper around the Lua C API. The wrapper adds some + * convenience functions and integrates well with modern C++. + * + * Luaxx is not designed like toLua, instead Luaxx is more of a 1 to 1 + * logical mapping of the lua API in C++. For example: in C you would write + * 'lua_pushnumber(L, 3)', in C++ with Luaxx you would write + * 'L.push(3)'. + * + * Every thing is contained in the 'lua' namespace and exceptions are thrown + * when a lua API function returns an error. Most of the functionality is + * contained in the lua::state class, which can be passed directly to lua C API + * functions (the compiler will automatically use the internal lua_State + * pointer). See the documentation for that class for more information. + */ + +namespace lua +{ + void StackDump(lua_State *L); + /** A generic lua exception. + */ + class exception : public std::exception { + public: + /// Constructor. + exception() : std::exception() { } + /// Constructor. + explicit exception(const char* desc) : std::exception(), description(desc) { } + virtual ~exception() throw() { } + /** Get a description of the error. + * @returns a C-string describing the error + */ + virtual const char* what() const throw() { + return description.c_str(); + } + private: + std::string description; + }; + + /** A lua runtime error. + * This is thrown when there was an error executing some lua code. + * @note This is not an std::runtime error. + */ + class runtime_error : public exception { + public: + /// Constructor. + runtime_error() : exception() { } + /// Constructor. + explicit runtime_error(const char* desc) : exception(desc) { } + virtual ~runtime_error() throw() { } + }; + + /** A syntax error. + */ + class syntax_error : public exception { + public: + /// Constructor. + syntax_error() : exception() { } + /// Constructor. + explicit syntax_error(const char* desc) : exception(desc) { } + virtual ~syntax_error() throw() { } + }; + + /** An error loading a lua file. + * This is thrown when a call to lua::loadfile failed because the file could + * not be opened or read. + */ + class file_error : public exception { + public: + /// Constructor. + file_error() : exception() { } + /// Constructor. + explicit file_error(const char* desc) : exception(desc) { } + virtual ~file_error() throw() { } + }; + + /** A memory allocation error. + */ + class bad_alloc : public exception, std::bad_alloc { + public: + /// Constructor. + bad_alloc() : lua::exception(), std::bad_alloc() { } + /// Constructor. + explicit bad_alloc(const char* desc) : lua::exception(desc), std::bad_alloc() { } + virtual ~bad_alloc() throw() { } + }; + + /** An error converting a lua type. + */ + class bad_conversion : public exception { + public: + /// Constructor. + bad_conversion() : exception() { } + /// Constructor. + explicit bad_conversion(const char* desc) : exception(desc) { } + virtual ~bad_conversion() throw() { } + }; + + /// A Lua table (this class does not have any data). + class table { }; + /// A Lua nil (this class does not have any data). + class nil { }; + /// A lua function (not a cfunction). + class function { }; + /// A lua userdatum + class userdata { }; + /// A lua light userdatum + class lightuserdata { }; + + typedef lua_CFunction cfunction; ///< A cfunction on the lua statck + typedef lua_Integer integer; ///< The default lua integer type + typedef lua_Number number; ///< The default lua number type + typedef lua_Reader reader; ///< The type of function used by lua_load + const int multiret = LUA_MULTRET; ///< LUA_MULTIRET + + /** This is the Luaxx equivalent of lua_State. + * The functions provided by this class, closely resemble those of the Lua C + * API. + */ + void StackDump(lua_State *L); + class state { + public: + state(); + state(lua_State* L); + state(const state& t) + { + managed=false; + L=t.L; + } + state& operator = (const state& t); + ~state(); + + operator lua_State*(); + + state& push(); + state& push(nil); + state& push(bool boolean); + template state& push(T number); + state& push(const char* s, size_t length); + state& push(const char* s); + state& push(const std::string& s); + state& push(cfunction f); + state& push(table); + state& push(void* p); + template state& pushlightuserdata(T p); + + template state& to(T& number, int index = -1); + template state& touserdata(T& p, int index = -1); + + template T as(T default_value, int index = -1); + template T as(int index = -1); + template T vpop() + { + T ret; + ret=as(); + pop(); + return ret; + } + template bool is(int index = -1); + + state& check(int narg); +#ifndef lua_Integer_int + state& check(int& i, int narg); +#endif + state& check(integer& i, int narg); +#ifndef lua_Integer_long + state& check(long& l, int narg); +#endif + state& check(std::string& s, int narg); + state& check(number& n, int narg); + + template void error(msg_t message); +#if 0 + template<> void error(const std::string& message); +#endif + + state& pcall(int nargs = 0, int nresults = 0, int on_error = 0); + state& call(int nargs = 0, int nresults = 0); + + state& checkstack(int size); + state& settop(int index); + int gettop(); + int size(); + bool empty(); + + state& insert(int index); + state& replace(int index); + state& remove(int index); + state& pop(int elements = 1); + + state& pushvalue(int index); + + state& newtable(); + bool newmetatable(const std::string& tname); + template userdata_t* newuserdata(); + void* newuserdata(size_t nbytes); + + state& gettable(int index = -2); + state& getfield(const std::string& k, int index = -1); + state& settable(int index = -3); + state& setfield(const std::string& k, int index = -2); + state& getmetatable(const std::string& tname); + bool getmetatable(int index); + + bool next(int index = -2); + + state& getglobal(const std::string& name); + state& setglobal(const std::string& name); + + state& loadfile(const std::string& filename); + state& loadstring(const std::string& s); + + template state& load(iterator_t begin, iterator_t end); + + size_t objlen(int index = -1); + + private: + lua_State* L; + bool managed; + + + + int throw_error(int code); + }; + + // template functions + + /** Push a number onto the stack. + * @tparam T the numeric type to push (should be automatically determined, + * if there is no specialization for the desired type, lua_pushnumber() will + * be used, and may fail) + * @param number the number to push + * @returns a reference to this lua::state + */ + template + state& state::push(T number) { + lua_pushnumber(L, number); + return *this; + } + + /** Push a light userdatum on to the stack. + * @tparam T the type of data to push (should be automatically determined) + * @param p the pointer to push + * @returns a reference to this lua::state + */ + template + state& state::pushlightuserdata(T p) { + lua_pushlightuserdata(L, p); + return *this; + } + + /** Check if the given index is of the given type (defaults to using + * lua_isnumber()). + * @tparam T the type to check for (the default, if no specializations + * match, does lua_isnumber()) + * @param index the index to check + * @note the default version (used if no specialization is matched) will + * check if the given value is a number + * @returns whether the value at the given index is a nil + */ + template + bool state::is(int index) { + return lua_isnumber(L, index); + } + + /** Get the value at index as the given numeric type. + * @tparam T they numeric type to static_cast() the numeric value on the + * stack to + * @param number where to store the value + * @param index the index to get + * @note This function does \em not pop the value from the stack. + * @todo Instead of throwing an exception here, we may just return an + * error code. + * @throws lua::bad_conversion if the value on the stack could not be + * converted to the indicated type + * @returns a reference to this lua::state + */ + template + state& state::to(T& number, int index) { + if (lua_isnumber(L, index)) + number = static_cast(lua_tonumber(L, index)); + else + throw bad_conversion("Cannot convert non 'number' value to number"); + + return *this; + } + + /** Get the value at index as (light) userdata. + * @tparam T the type of data pointed to (pointer is returned as + * reinterpret_cast()) + * @param p the pointer to store the value in + * @param index the index to get + * @note This function does \em not pop the value from the stack. + * @todo Instead of throwing an exception here, we may just return an + * error code. + * @throws lua::bad_conversion if the value on the stack could not be + * converted to the indicated type + * @returns a reference to this lua::state + */ + template + state& state::touserdata(T& p, int index) { + if (lua_isuserdata(L, index)) + p = reinterpret_cast(lua_touserdata(L, index)); + else + throw bad_conversion("Cannot convert non 'userdata' or 'lightuserdata' value to userdata"); + + return *this; + } + + /** Get the value at index as the given type. + * @tparam T the type to retrieve the value on the stack as (the default + * template function uses lua_tonumber(), specializations may cause + * different behavior) + * @param default_value this value is returned if the conversion fails + * @param index the index to get + * @note This function does \em not pop the value from the stack. + * @returns the indicated value from the stack or the default value if + * the conversion fails + */ + template + T state::as(T default_value, int index) { + if (lua_isnumber(L, index)) + return static_cast(lua_tonumber(L, index)); + else + return default_value; + } + + /** Get the value at index as the given type. + * @tparam T the expected type of the value + * @param index the index to get + * + * @note This function does \em not pop the value from the stack. + * @note The default version of this function uses lua_tonumber() but + * specializations may cause different behavior. + * + * @todo Instead of throwing an exception here, we may just return an + * error code. + * + * @throws lua::bad_conversion if the value on the stack could not be + * converted to the indicated type + * + * This function will return the value on the stack as the given type. If + * the value is not of the given type no conversion will be + * performed and lua::bad_conversion will be thrown. There are some + * exceptions to this rule, for example, numbers will be converted to + * strings and vice-versa (conversion is only performed if the matching + * lua_is*() function returns true). The state::to() function should be + * used to perform automatic conversion. + * + * @returns the indicated value as the given type if possible + */ + template + T state::as(int index) { + if (lua_isnumber(L, index)) + return static_cast(lua_tonumber(L, index)); + else + throw bad_conversion("Cannot convert non 'number' value to number"); + } + + /** Create a new userdatum on the stack. + * @tparam userdata_t the type of the userdata (will be passed to sizeof()) + * + * This function creates a new userdatum on the stack the size of + * userdata_t and return a pointer to it. + * @returns a pointer to the new userdatum + */ + template + userdata_t* state::newuserdata() { + return reinterpret_cast(lua_newuserdata(L, sizeof(userdata_t))); + } + + /** Generate a Lua error. + * @tparam msg_t the type of error message data (should be automatically + * determined) + * @param message the error message/value + * @note This function is used to raise errors from lua::cfunctions. + * @note This function never returns, instead it throws an exception + * caught by the intepreter. + */ + template + void state::error(msg_t message) { + push(message); + lua_error(L); + } + + /** Load a sequence of data as a Lua chunk. + * @tparam iterator_t the type of iterator to use (should be automatically + * determined) + * @param begin an iterator to the start of the sequence + * @param end an iterator to the end of the sequence (one past the + * end) + * + * This function takes a sequence of data and attempts to convert it + * into a Lua chunk. The type of data passed must be able to be + * converted into an 8-bit char. + * + * @note This function should automatically detect if the data is text + * or binary. + * + * @returns a reference to this lua::state + */ + template + state& state::load(iterator_t begin, iterator_t end) { + // convert the data to characters + std::vector chunk(begin, end); + + // Here we use the address of the first element of our vector. + // This works because the data in std::vectors is contiguous. + throw_error(luaL_loadbuffer(L, &(*chunk.begin()), chunk.size(), NULL)); + return *this; + } + + + // template specializations + template<> state& state::to(bool& boolean, int index); + template<> state& state::to(std::string& string, int index); + + template<> bool state::as(bool default_value, int index); + template<> std::string state::as(std::string default_value, int index); + template<> bool state::as(int index); + template<> std::string state::as(int index); + + template<> bool state::is(int index); + template<> bool state::is(int index); + template<> bool state::is(int index); + template<> bool state::is(int index); + template<> bool state::is(int index); + template<> bool state::is(int index); + template<> bool state::is(int index); + template<> bool state::is(int index); + + + // inline functions + + /** Convert a lua::state to a lua_State*. + * This operator allows lua::state to behave like a lua_State + * pointer. + * + * @note This should be used as a last result to interoperate with C + * code. This may be removed in future versions of Luaxx. + */ + inline state::operator lua_State*() { + return L; + } + + /** Throws exceptions for error return codes. + * @param code the return code + * + * This function throws an exception based on the error it was passed. + * If it is passed a 0 it will not throw anything. + * + * @todo In the future this function may check an exception mask + * before throwing an error. + * + * @returns the code it was passed + */ + inline int state::throw_error(int code) { + std::string error; + + // below, we package lua errors into exceptions + switch (code) { + case 0: + break; + case LUA_ERRSYNTAX: + to(error).pop(); + throw syntax_error(error.c_str()); + case LUA_ERRMEM: + to(error).pop(); + throw bad_alloc(error.c_str()); + case LUA_ERRRUN: + to(error).pop(); + throw runtime_error(error.c_str()); + case LUA_ERRFILE: + to(error).pop(); + throw file_error(error.c_str()); + default: + to(error).pop(); + throw exception(error.c_str()); + } + return code; + } + +} + +#endif diff --git a/plugins/Dfusion/src/luamain.cpp b/plugins/Dfusion/src/luamain.cpp new file mode 100644 index 000000000..3f9cfdad7 --- /dev/null +++ b/plugins/Dfusion/src/luamain.cpp @@ -0,0 +1,69 @@ +#include "luamain.h" +#include + + +lua::glua* lua::glua::ptr=0; +lua::glua::glua() +{ + RegBasics(mystate); +} +lua::state &lua::glua::Get() +{ + if(!glua::ptr) + glua::ptr=new glua(); + return glua::ptr->mystate; +} + + +int lua_Ver_Lua(lua_State *L) +{ + lua::state st(L); + st.push(LUA_RELEASE); + return 1; +} + + +static const struct luaL_reg lua_basic_lib [] = +{ + {"getluaver", lua_Ver_Lua}, + {NULL, NULL} /* sentinel */ +}; +void lua::RegBasics(lua::state &L) +{ + luaL_openlibs(L); + RegFunctions(L,lua_basic_lib); +} + +void lua::RegFunctions(lua::state &L,luaL_reg const*arr) +{ + luaL_reg const *cur=arr; + while(cur->name!=NULL) + { + lua_pushcfunction(L, cur->func); + lua_setglobal(L, cur->name); + + cur++; + } +} +void lua::RegFunctionsLocal(lua::state &L,luaL_reg const*arr) +{ + luaL_reg const *cur=arr; + while(cur->name!=NULL) + { + lua_pushcfunction(L, cur->func); + //lua_setglobal(L, cur->name); + L.setfield(cur->name); + + cur++; + } +} +string lua::DebugDump(lua::state &L) +{ + L.getglobal("debug"); + L.getfield("traceback"); + L.call(0,1); + string ret=L.as(); + //cout<<"StackTrace:"< +#include +#define LOG std::cout +/** @file + * Luaxx implementation file. + */ + +namespace lua +{ + void StackDump(lua_State *L) + { + int i; + int top = lua_gettop(L); + for (i = 1; i <= top; i++) /* repeat for each level */ + { + int t = lua_type(L, i); + LOG<on the stack. This can + * confuse lua::state::next(); + * + * @returns the indicated value from the stack or the default value if the + * conversion fails + */ + template<> + std::string state::as(std::string default_value, int index) { + if (lua_isstring(L, index)) + return std::string(lua_tostring(L, index), lua_strlen(L, index)); + else + return default_value; + } + + /** Check an argument of the current function. + * @param narg the argument number to check + * + * This function will throw a lua error if there is no argument at the + * given position. + * + * @note This function is meant to be called from with in a lua::cfunction. + * The error throw is internal to the lua interpreter. When compiled as + * C++, a C++ exception is thrown, so the stack is properly unwound. This + * exception is not meant to be caught. + */ + state& state::check(int narg) { + luaL_checkany(L, narg); + return *this; + } + +#ifndef lua_Integer_int + /** Check an argument of the current function. + * @param i the int to hold the returned value + * @param narg the argument number to check + * + * This function checks if the given argument number is an int. + * + * @note This function is meant to be called from with in a + * lua::cfunction. The error throw is internal to the lua intrepeter. + * When compiled as C++, a C++ exception is thrown, so the stack is + * properly unwound. This exception is not meant to be caught. + */ + state& state::check(int& i, int narg) { + i = luaL_checkint(L, narg); + return *this; + } +#endif + + /** Check an argument of the current function. + * @param i the lua::integer (lua_Integer) to hold the returned value + * @param narg the argument number to check + * + * This function checks if the given argument number is an integer. + * + * @note This is different from lua::check(int(), ...). It returns a + * lua::integer (lua_Integer), which may not be an int. + * + * @note This function is meant to be called from with in a + * lua::cfunction. The error throw is internal to the lua intrepeter. + * When compiled as C++, a C++ exception is thrown, so the stack is + * properly unwound. This exception is not meant to be caught. + */ + state& state::check(integer& i, int narg) { + i = luaL_checkinteger(L, narg); + return *this; + } + +#ifndef lua_Integer_long + /** Check an argument of the current function. + * @param l the long to hold the returned value + * @param narg the argument number to check + * + * This function checks if the given argument number is a long. + * + * @note This function is meant to be called from with in a + * lua::cfunction. The error throw is internal to the lua intrepeter. + * When compiled as C++, a C++ exception is thrown, so the stack is + * properly unwound. This exception is not meant to be caught. + */ + state& state::check(long& l, int narg) { + l = luaL_checklong(L, narg); + return *this; + } +#endif + + /** Check an argument of the current function. + * @param s the string to hold the returned value + * @param narg the argument number to check + * + * This function checks if the given argument number is a string. + * + * @note This function is meant to be called from with in a + * lua::cfunction. The error throw is internal to the lua intrepeter. + * When compiled as C++, a C++ exception is thrown, so the stack is + * properly unwound. This exception is not meant to be caught. + */ + state& state::check(std::string& s, int narg) { + const char* c; + size_t l; + c = luaL_checklstring(L, narg, &l); + + s.assign(c, l); + + return *this; + } + + /** Check an argument of the current function. + * @param n the lua::number (lua_Number) to hold the returned value + * @param narg the argument number to check + * + * This function checks if the given argument number is a lua::number + * (lua_Number, a double by default). + * + * @note This function is meant to be called from with in a lua::cfunction. + * The error throw is internal to the lua interpreter. When compiled as + * C++, a C++ exception is thrown, so the stack is properly unwound. This + * exception is not meant to be caught. + */ + state& state::check(number& n, int narg) { + n = luaL_checknumber(L, narg); + return *this; + } + +#if 0 + /** [specialization] Generate a Lua error (T = std::string). + */ + template<> + void state::error(const std::string& message) { + push(message); + lua_error(L); + } +#endif + + /** Call a lua function. + * @param nargs the number of args to pass to the function + * @param nresults the number of values to return from the function + * @param on_error A stack index where the error handling function is + * stored. + * @note The error handling function must be pushed in the stack + * before the function to be called and its arguments. + * @returns a reference to this lua::state + */ + state& state::pcall(int nargs, int nresults, int on_error) { + throw_error(lua_pcall(L, nargs, nresults, on_error)); + return *this; + } + + /** Call a lua function in unprotected mode. + * @param nargs the number of args to pass to the function + * @param nresults the number of values to return from the function + * stored. + * @note If there is an error in the call the program will terminate. + * @returns a reference to this lua::state + */ + state& state::call(int nargs, int nresults) { + lua_call(L, nargs, nresults); + return *this; + } + + /** Ensure the stack is at least the given size. + * @param size the size to use + * + * If the stack is smaller than the given size, it will grow to the + * specified size. + * + * @exception lua::exception Thrown if the operation fails. + * @returns a reference to this lua::state + */ + state& state::checkstack(int size) { + if (!lua_checkstack(L, size)) + throw lua::exception("Error growing the stack"); + return *this; + } + + /** Set a new index as the top of the stack. + * @param index the index to use as the new top + * @note If the previous top was higher than the new one, top values + * are discarded. Otherwise this function pushs nils on to the stack + * to get the proper size. + * @returns a reference to this lua::state + */ + state& state::settop(int index) { + lua_settop(L, index); + return *this; + } + + /** Get the number of elements in the stack. + * @note This value is also the index of the top element. + * @returns the number of elements in the stack + */ + int state::gettop() { + return lua_gettop(L); + } + + /** Get the number of elements in the stack. + * @note This value is also the index of the top element. + * @returns the number of elements in the stack + */ + int state::size() { + return lua_gettop(L); + } + + /** Check if the stack is empty. + * @returns true if the stack is empty, false otherwise + */ + bool state::empty() { + return !lua_gettop(L); + } + + /** Move the top element to the given index. + * @param index the index to insert at + * @note All elements on top of the given index are shifted up to open + * space for this element. + * @returns a reference to this lua::state + */ + state& state::insert(int index) { + lua_insert(L, index); + return *this; + } + + /** Replace the given index with the top element. + * @param index the index to replae + * @returns a reference to this lua::state + */ + state& state::replace(int index) { + lua_replace(L, index); + return *this; + } + + /** Remove the given index from the stack. + * @param index the index to remove + * @note Elements are shifted down to fill in the empty spot. + * @returns a reference to this lua::state + */ + state& state::remove(int index) { + lua_remove(L, index); + return *this; + } + + /** Remove the given number of elemens from the stack. + * @param elements the number of elements to remove + * @returns a reference to this lua::state + */ + state& state::pop(int elements) { + lua_pop(L, elements); + return *this; + } + + /** Push a copy of the element at the given index to the top of the + * stack. + * @param index the index of the element to copy + * @returns a reference to this lua::state + */ + state& state::pushvalue(int index) { + lua_pushvalue(L, index); + return *this; + } + + /** Create a new table on the stack. + * @returns a reference to this lua::state + */ + state& state::newtable() { + lua_newtable(L); + return *this; + } + + /** Create a new metatable and add it to the registry. + * @param tname the name to use for the new metatable in the registry + * + * This function creates a new metatable and adds it to the registry + * with the given key. This function also pushes the new metatable + * onto the stack. + * + * @note Regardless of the return value, the new metatable is always pushed + * on to the stack. + * + * @return true if a new metatable was created, false if the registry + * alread has a key with the given name. + */ + bool state::newmetatable(const std::string& tname) { + return luaL_newmetatable(L, tname.c_str()); + } + + /** Create a new userdatum on the stack. + * @param nbytes the size of the new userdatum + * @return a pointer to the new userdatum + */ + void* state::newuserdata(size_t nbytes) { + return lua_newuserdata(L, nbytes); + } + + /** Get a value from a table on the stack. + * @param index the index the table is stored at + * + * This function gets a value from the table at the given index and + * pushes it onto the stack. + * + * @note You should have already pushed the key used to reference this + * value onto the stack before calling this function. + * + * @returns a reference to this lua::state + */ + state& state::gettable(int index) { + lua_gettable(L, index); + return *this; + } + + /** Get a value from a table on the stack. + * @param k the key + * @param index the index the table is stored at + * + * This function gets a value from the table at the given index and + * pushes it onto the stack. + * + * @returns a reference to this lua::state + */ + state& state::getfield(const std::string& k, int index) { + lua_getfield(L, index, k.c_str()); + return *this; + } + + /** Set a value in a table. + * @param index the index the table is stored at + * + * This function sets a value in a table stored at the given index. + * + * @note The key and value to be used should have already been pushed + * on the stack in that order. + * + * @returns a reference to this lua::state + */ + state& state::settable(int index) { + lua_settable(L, index); + return *this; + } + + /** Set a field in a table. + * @param k the key + * @param index the index the table is stored at + * + * This function sets a value in a table stored at the given index. + * + * @note The value to be used should be on the top of the stack. + * + * @returns a reference to this lua::state + */ + state& state::setfield(const std::string& k, int index) { + lua_setfield(L, index, k.c_str()); + return *this; + } + + /** Get the metatable associated with the given registry entry. + * @param tname the name in the registry + * + * This function gets the metatable associated with the given key in + * the registry. The resulting metatable is pushed onto the stack. + * + * @note This function uses luaL_getmetatable() internally. + * + * @returns a reference to this lua::state + */ + state& state::getmetatable(const std::string& tname) { + luaL_getmetatable(L, tname.c_str()); + return *this; + } + + /** Get the metatable of the value at the given index. + * @param index the index the value is stored at + * + * This function pushes on to the stack the metatabe of the value at + * the given index. + * + * @note This function uses lua_getmetatable() internally. + * + * @returns false if the value at the given index does not have a + * metatable or if the index is not valid + */ + bool state::getmetatable(int index) { + return lua_getmetatable(L, index); + } + + /** Get the next key value pair from a table on the stack. + * @param index the stack index the table is at + * + * This function pops a key from the stack and pushes the next key + * value pair to the stack. The key will be stored at index -2 and + * the value will be at index -1. The key is expected to be on the + * top of the stack. + * + * @note While traversing a table, do not call + * lua::state::to(std::string()) directly on a key, unless you know + * that the key is actually a string. lua::state::to(std::string()) + * changes the value at the given index; this confuses the next call + * to lua::state::next(). + * + * While Loop Example: + * @code + * while(L.next() != 0) { + * // do stuff + * L.pop(); + * } + * @endcode + * + * For Loop Example: + * @code + * for(L.push(lua::nil()); L.next(); L.pop()) { + * // do stuff + * } + * @endcode + * + * @returns true as long as there are remaining items in the table + */ + bool state::next(int index) { + return lua_next(L, index); + } + + /** Load a global symbol onto the stack. + * @param name the name of the global to load + * + * This function loads a global symbol onto the stack from the lua + * state. + * + * @returns a reference to this lua::state + */ + state& state::getglobal(const std::string& name) { + lua_getglobal(L, name.c_str()); + return *this; + } + + /** Set a global symbol. + * @param name the name of the global to set + * + * This function sets/creates a global symbol from the value above it + * on the stack. + * + * @note You should have pushed the value of the symbol onto the stack + * before calling this function. + * + * @returns a reference to this lua::state + */ + state& state::setglobal(const std::string& name) { + lua_setglobal(L, name.c_str()); + return *this; + } + + /** Load a file as a Lua chunk. + * @param filename the name of the file to load + * @returns a reference to this lua::state + */ + state& state::loadfile(const std::string& filename) { + throw_error(luaL_loadfile(L, filename.c_str())); + return *this; + } + + /** Load a string as a Lua chunk. + * @param s the string to load + * @returns a reference to this lua::state + */ + state& state::loadstring(const std::string& s) { + throw_error(luaL_loadstring(L, s.c_str())); + return *this; + } + + /** Get the length of a value on the stack. + * @param index the index the value is stored at + * @returns the length of the indicated value + */ + size_t state::objlen(int index) { + return lua_objlen(L, index); + } + + /** Get the value at index as a bool. + * @param boolean where to store the value + * @param index the index to get + * @note This function does \em not pop the value from the stack. + * @todo Instead of throwing an exception here, we may just return an + * error code. + * @throws lua::bad_conversion if the value on the stack could not be + * converted to the indicated type + * @returns a reference to this lua::state + */ + template<> + state& state::to(bool& boolean, int index) { + if (lua_isboolean(L, index)) + boolean = lua_toboolean(L, index); + else + throw bad_conversion("Cannot convert non 'boolean' value to bool"); + + return *this; + } + + /** Get the value at index as a string. + * @param string where to store the value + * @param index the index to get + * @note This function does \em not pop the value from the stack. + * @todo Instead of throwing an exception here, we may just return an + * error code. + * + * @note lua::state::to(std::string()) will convert the value at the + * indicated index to a string on the stack. This can + * confuse lua::state::next(); + * + * @throws lua::bad_conversion if the value on the stack could not be + * converted to the indicated type + * @returns a reference to this lua::state + */ + template<> + state& state::to(std::string& string, int index) { + if (lua_isstring(L, index)) + string.replace(0, std::string::npos, lua_tostring(L, index), lua_strlen(L, index)); + else + throw bad_conversion("Cannot convert value to string"); + + return *this; + } + + /** Get the value at index as a bool. + * @param default_value this value is returned if the conversion fails + * @param index the index to get + * @note This function does \em not pop the value from the stack. + * @returns the indicated value from the stack or the default value if the + * conversion fails + */ + template<> + bool state::as(bool default_value, int index) { + if (lua_isboolean(L, index)) + return lua_toboolean(L, index); + else + return default_value; + } + + /** [specialization] Get the value at index as a bool (T = bool). + */ + template<> + bool state::as(int index) { + if (lua_isboolean(L, index)) + return lua_toboolean(L, index); + else + throw bad_conversion("Cannot convert non 'boolean' value to bool"); + } + + /** [specialization] Get the value at index as a string (T = std::string). + * @note lua::state::as(std::string()) will convert the value at the + * indicated index to a string on the stack. This can confuse + * lua::state::next(); + */ + template<> + std::string state::as(int index) { + if (lua_isstring(L, index)) + return std::string(lua_tostring(L, index), lua_strlen(L, index)); + else + throw bad_conversion("Cannot convert value to string"); + } + + /** [specialization] Check if the given index is a nil (T = lua::nil). + */ + template<> + bool state::is(int index) { + return lua_isnil(L, index); + } + + /** [specialization] Check if the given index is a boolean (T = bool). + */ + template<> + bool state::is(int index) { + return lua_isboolean(L, index); + } + + /** [specialization] Check if the given index is a string (T = std::string). + */ + template<> + bool state::is(int index) { + return lua_isstring(L, index); + } + + /** [specialization] Check if the given index is a table (T = lua::table). + */ + template<> + bool state::is
(int index) { + return lua_istable(L, index); + } + + /** [specialization] Check if the given index is a C function (T = + * lua::cfunction). + */ + template<> + bool state::is(int index) { + return lua_iscfunction(L, index); + } + + /** [specialization] Check if the given index is a function (T = + * lua::function). + */ + template<> + bool state::is(int index) { + return lua_isfunction(L, index); + } + + /** [specialization] Check if the given index is userdata (T = + * lua::userdata). + */ + template<> + bool state::is(int index) { + return lua_isuserdata(L, index); + } + + /** [specialization] Check if the given index is light userdata (T = + * lua::lightuserdata). + */ + template<> + bool state::is(int index) { + return lua_islightuserdata(L, index); + } + +} + From 3106606a4ebd326eb3ba5c29c634770a25c1aa83 Mon Sep 17 00:00:00 2001 From: Warmist Date: Sat, 16 Jul 2011 20:43:57 +0300 Subject: [PATCH 4/8] OnTick working! Signed-off-by: Warmist --- plugins/Dfusion/dfusion.cpp | 28 ++++++++++++++++++++-------- plugins/Dfusion/include/luamain.h | 2 ++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index d11d6c111..4e31add47 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -5,7 +5,8 @@ #include #include -#include + + #include @@ -13,7 +14,7 @@ using std::vector; using std::string; using namespace DFHack; - +static SDL::Mutex *mymutex=0; DFhackCExport command_result dfusion (Core * c, vector & parameters); @@ -27,7 +28,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector { commands.clear(); commands.push_back(PluginCommand("DFusion","Init dfusion system.",dfusion)); - + mymutex=SDL_CreateMutex(); return CR_OK; } @@ -48,6 +49,15 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) c->con.print("Time delta = %d ms\n", delta); } return CR_OK;*/ + SDL_mutexP(mymutex); //TODO: make lua thread safe (somehow)... + lua::state s=lua::glua::Get(); + s.getglobal("OnTick"); + if(s.is()) + { + s.pcall(); + } + s.settop(0); + SDL_mutexV(mymutex); return CR_OK; } @@ -56,15 +66,17 @@ DFhackCExport command_result dfusion (Core * c, vector & parameters) { // do stuff Console &con=c->con; - + SDL_mutexP(mymutex); try{ - lua::glua::Get().loadfile("dfusion/init.lua"); - lua::glua::Get().pcall(0,0); + lua::glua::Get().loadfile("dfusion/init.lua"); //load script + lua::glua::Get().pcall(0,0);// run it + } catch(lua::exception &e) { - con.printerr("Error:%s",e.what()); + con.printerr("Error:%s\n",e.what()); } - + lua::glua::Get().settop(0);// clean up + SDL_mutexV(mymutex); return CR_OK; } diff --git a/plugins/Dfusion/include/luamain.h b/plugins/Dfusion/include/luamain.h index 55c780582..ff4a9d138 100644 --- a/plugins/Dfusion/include/luamain.h +++ b/plugins/Dfusion/include/luamain.h @@ -3,6 +3,8 @@ #include using std::string; + + extern "C" { #include "lua.h" #include "lauxlib.h" From e47d05eeb4162e07728bcc389e7e9dd14a2676a1 Mon Sep 17 00:00:00 2001 From: Warmist Date: Sat, 16 Jul 2011 22:08:58 +0300 Subject: [PATCH 5/8] Full DFHack::Console to lua binding. Signed-off-by: Warmist --- plugins/Dfusion/dfusion.cpp | 24 +++-- plugins/Dfusion/include/lua_Console.h | 13 +++ plugins/Dfusion/include/luamain.h | 6 +- plugins/Dfusion/src/lua_Console.cpp | 137 ++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 13 deletions(-) create mode 100644 plugins/Dfusion/include/lua_Console.h create mode 100644 plugins/Dfusion/src/lua_Console.cpp diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index 4e31add47..33d2503a7 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -6,15 +6,14 @@ #include - - -#include +#include "luamain.h" +#include "lua_Console.h" using std::vector; using std::string; using namespace DFHack; -static SDL::Mutex *mymutex=0; +static SDL::Mutex* mymutex=0; DFhackCExport command_result dfusion (Core * c, vector & parameters); @@ -27,7 +26,10 @@ DFhackCExport const char * plugin_name ( void ) DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) { commands.clear(); - commands.push_back(PluginCommand("DFusion","Init dfusion system.",dfusion)); + //maybe remake it to run automaticaly + lua::RegisterConsole(lua::glua::Get(),&c->con); + + commands.push_back(PluginCommand("dfusion","Init dfusion system.",dfusion)); mymutex=SDL_CreateMutex(); return CR_OK; } @@ -41,7 +43,7 @@ DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_onupdate ( Core * c ) { - /*if(timering == true) + /*if(timering == true) //TODO maybe reuse this to make it run less often. { uint64_t time2 = GetTimeMs64(); uint64_t delta = time2-timeLast; @@ -49,7 +51,7 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) c->con.print("Time delta = %d ms\n", delta); } return CR_OK;*/ - SDL_mutexP(mymutex); //TODO: make lua thread safe (somehow)... + SDL_mutexP(mymutex); lua::state s=lua::glua::Get(); s.getglobal("OnTick"); if(s.is()) @@ -67,16 +69,18 @@ DFhackCExport command_result dfusion (Core * c, vector & parameters) // do stuff Console &con=c->con; SDL_mutexP(mymutex); + lua::state s=lua::glua::Get(); + try{ - lua::glua::Get().loadfile("dfusion/init.lua"); //load script - lua::glua::Get().pcall(0,0);// run it + s.loadfile("dfusion/init.lua"); //load script + s.pcall(0,0);// run it } catch(lua::exception &e) { con.printerr("Error:%s\n",e.what()); } - lua::glua::Get().settop(0);// clean up + s.settop(0);// clean up SDL_mutexV(mymutex); return CR_OK; } diff --git a/plugins/Dfusion/include/lua_Console.h b/plugins/Dfusion/include/lua_Console.h new file mode 100644 index 000000000..a6430dcbf --- /dev/null +++ b/plugins/Dfusion/include/lua_Console.h @@ -0,0 +1,13 @@ +#ifndef LUA_CONSOLE_H +#define LUA_CONSOLE_H +#include +#include "luamain.h" + +namespace lua +{ + +void RegisterConsole(lua::state &st, DFHack::Console *c); + +} + +#endif \ No newline at end of file diff --git a/plugins/Dfusion/include/luamain.h b/plugins/Dfusion/include/luamain.h index ff4a9d138..aee073729 100644 --- a/plugins/Dfusion/include/luamain.h +++ b/plugins/Dfusion/include/luamain.h @@ -1,5 +1,5 @@ -#ifndef LUASTUFF_H -#define LUASTUFF_H +#ifndef LUAMAIN_H +#define LUAMAIN_H #include using std::string; @@ -37,4 +37,4 @@ namespace lua -#endif // LUASTUFF_H +#endif // LUAMAIN_H diff --git a/plugins/Dfusion/src/lua_Console.cpp b/plugins/Dfusion/src/lua_Console.cpp new file mode 100644 index 000000000..f45fa8d56 --- /dev/null +++ b/plugins/Dfusion/src/lua_Console.cpp @@ -0,0 +1,137 @@ +#include "lua_Console.h" +//TODO error management. Using lua error? or something other? +static DFHack::Console* GetConsolePtr(lua::state &st) +{ + int t=st.gettop(); + st.getglobal("Console"); + st.getfield("__pointer"); + DFHack::Console* c=static_cast(lua_touserdata(st,-1)); + st.settop(t); + return c; +} +static int lua_Console_print(lua_State *S) +{ + lua::state st(S); + int t=st.gettop(); + DFHack::Console* c=GetConsolePtr(st); + c->print("%s",st.as(t).c_str()); + return 0; +} + +static int lua_Console_printerr(lua_State *S) +{ + lua::state st(S); + int t=st.gettop(); + DFHack::Console* c=GetConsolePtr(st); + c->printerr("%s",st.as(t).c_str()); + return 0; +} + +static int lua_Console_clear(lua_State *S) +{ + lua::state st(S); + DFHack::Console* c=GetConsolePtr(st); + c->clear(); + return 0; +} +static int lua_Console_gotoxy(lua_State *S) +{ + lua::state st(S); + DFHack::Console* c=GetConsolePtr(st); + c->gotoxy(st.as(1,1),st.as(1,2)); + return 0; +} +static int lua_Console_color(lua_State *S) +{ + lua::state st(S); + DFHack::Console* c=GetConsolePtr(st); + c->color( static_cast(st.as(-1,1)) ); + return 0; +} +static int lua_Console_reset_color(lua_State *S) +{ + lua::state st(S); + DFHack::Console* c=GetConsolePtr(st); + c->reset_color(); + return 0; +} +static int lua_Console_cursor(lua_State *S) +{ + lua::state st(S); + DFHack::Console* c=GetConsolePtr(st); + c->cursor(st.as(1)); + return 0; +} +static int lua_Console_msleep(lua_State *S) +{ + lua::state st(S); + DFHack::Console* c=GetConsolePtr(st); + c->msleep(st.as(1)); + return 0; +} +static int lua_Console_get_columns(lua_State *S) +{ + lua::state st(S); + DFHack::Console* c=GetConsolePtr(st); + st.push(c->get_columns()); + return 1; +} +static int lua_Console_get_rows(lua_State *S) +{ + lua::state st(S); + DFHack::Console* c=GetConsolePtr(st); + st.push(c->get_rows()); + return 1; +} +static int lua_Console_lineedit(lua_State *S) +{ + lua::state st(S); + DFHack::Console* c=GetConsolePtr(st); + string ret; + int i=c->lineedit(st.as(1),ret); + st.push(ret); + st.push(i); + return 2;// dunno if len is needed... +} +static int lua_Console_history_add(lua_State *S) +{ + lua::state st(S); + DFHack::Console* c=GetConsolePtr(st); + c->history_add(st.as(1)); + return 0; +} +/*static int lua_Console_history_clear(lua_State *S) //TODO someday add this +{ + lua::state st(S); + DFHack::Console* c=GetConsolePtr(st); + c->history_clear(); + return 0; +}*/ +const luaL_Reg lua_console_func[]= +{ + {"print",lua_Console_print}, + {"printerr",lua_Console_printerr}, + {"clear",lua_Console_clear}, + {"gotoxy",lua_Console_gotoxy}, + {"color",lua_Console_color}, + {"reset_color",lua_Console_reset_color}, + {"cursor",lua_Console_cursor}, + {"msleep",lua_Console_msleep}, + {"get_columns",lua_Console_get_columns}, + {"get_rows",lua_Console_get_rows}, + {"lineedit",lua_Console_lineedit}, + {"history_add",lua_Console_history_add}, + //{"history_clear",lua_Console_history_clear}, + {NULL,NULL} +}; +void lua::RegisterConsole(lua::state &st, DFHack::Console *c) +{ + st.newtable(); + + st.pushlightuserdata(c); + st.setfield("__pointer"); + + lua::RegFunctionsLocal(st, lua_console_func); + //TODO add color consts + st.setglobal("Console"); +} From fc68387ea38f7f803a9284464e75822abaed2930 Mon Sep 17 00:00:00 2001 From: Warmist Date: Sat, 16 Jul 2011 22:23:44 +0300 Subject: [PATCH 6/8] Improved error checking (and flood protection) Signed-off-by: Warmist --- plugins/Dfusion/dfusion.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index 33d2503a7..1243de30e 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -56,7 +56,14 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) s.getglobal("OnTick"); if(s.is()) { - s.pcall(); + try{ + s.pcall(); + } + catch(lua::exception &e) + { + c->con.printerr("Error OnTick:%s\n",e.what()); + c->con.msleep(1000); + } } s.settop(0); SDL_mutexV(mymutex); @@ -74,7 +81,6 @@ DFhackCExport command_result dfusion (Core * c, vector & parameters) try{ s.loadfile("dfusion/init.lua"); //load script s.pcall(0,0);// run it - } catch(lua::exception &e) { From d0c2f3b9f5b5186e21c1f225a2ad3420972a89c1 Mon Sep 17 00:00:00 2001 From: Warmist Date: Sun, 17 Jul 2011 12:00:29 +0300 Subject: [PATCH 7/8] Functioncall minilib testing --- plugins/Dfusion/dfusion.cpp | 28 +++++---- plugins/Dfusion/include/functioncall.h | 23 ++++++++ plugins/Dfusion/src/functioncall.cpp | 81 ++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 plugins/Dfusion/include/functioncall.h create mode 100644 plugins/Dfusion/src/functioncall.cpp diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index 6f14fb66c..e1792ba5f 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -2,14 +2,13 @@ #include #include #include -#include +#include #include #include -#include - #include "luamain.h" #include "lua_Console.h" +#include "functioncall.h" using std::vector; using std::string; @@ -20,8 +19,8 @@ static SDL::Mutex* mymutex=0; DFhackCExport command_result dfusion (Core * c, vector & parameters); DFhackCExport command_result lua_run (Core * c, vector & parameters); -typedef -int __stdcall (*dfprint)(const char*, char, char,void *ptr) ; + typedef + int (__thiscall *dfprint)(const char*, char, char,void *) ; DFhackCExport const char * plugin_name ( void ) { @@ -81,15 +80,20 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result lua_run (Core * c, vector & parameters) { + //testing part{ c->Suspend(); - std::stringstream ss; - ss<>i; - dfprint mprint=(dfprint)(0x27F030+i); - mprint("Hello world",1,4,0); + FunctionCaller caller(c->p->getBase()); + std::vector args; + args.push_back((size_t)"Hello world"); + args.push_back(4); + args.push_back(4); + args.push_back(0); + dfprint mprint=(dfprint)(0x27F030+c->p->getBase()); + mprint("Hello world",4,4,0); + caller.CallFunction((0x27F030),FunctionCaller::THIS_CALL,args); c->Resume(); return CR_OK; + //}end testing Console &con=c->con; SDL_mutexP(mymutex); lua::state s=lua::glua::Get(); @@ -116,7 +120,7 @@ DFhackCExport command_result dfusion (Core * c, vector & parameters) { Console &con=c->con; - con.print("%x\n",c->vinfo->getBase()); + con.print("%x\n",c->p->getBase()); SDL_mutexP(mymutex); lua::state s=lua::glua::Get(); diff --git a/plugins/Dfusion/include/functioncall.h b/plugins/Dfusion/include/functioncall.h new file mode 100644 index 000000000..b0cb07038 --- /dev/null +++ b/plugins/Dfusion/include/functioncall.h @@ -0,0 +1,23 @@ +#ifndef FUNCTIONCALL__H +#define FUNCTIONCALL__H +#include +using std::vector; +class FunctionCaller +{ +public: + enum callconv + { + STD_CALL, //__stdcall - all in stack + FAST_CALL, //__fastcall - as much in registers as fits + THIS_CALL, //__thiscall - eax ptr to this, rest in stack + CDECL_CALL //__cdecl - same as stdcall but no stack realign + }; + + FunctionCaller(size_t base):base_(base){}; + + int CallFunction(size_t func_ptr,callconv conv,const vector &arguments); +private: + size_t base_; +}; + +#endif //FUNCTIONCALL__H \ No newline at end of file diff --git a/plugins/Dfusion/src/functioncall.cpp b/plugins/Dfusion/src/functioncall.cpp new file mode 100644 index 000000000..085a2e7d2 --- /dev/null +++ b/plugins/Dfusion/src/functioncall.cpp @@ -0,0 +1,81 @@ +#include "functioncall.h" +#define __F_TDEF(CONV,CONV_,tag) typedef int(CONV_ *F_TYPE##CONV##tag) +#define __F_T(CONV,tag) F_TYPE##CONV##tag +#define __F_TYPEDEFS(CONV,CONV_) __F_TDEF(CONV,CONV_,1)(int);\ + __F_TDEF(CONV,CONV_,2)(int,int);\ + __F_TDEF(CONV,CONV_,3)(int,int,int);\ + __F_TDEF(CONV,CONV_,4)(int,int,int,int);\ + __F_TDEF(CONV,CONV_,5)(int,int,int,int,int);\ + __F_TDEF(CONV,CONV_,6)(int,int,int,int,int,int);\ + __F_TDEF(CONV,CONV_,7)(int,int,int,int,int,int,int) + + +#define __FCALL(CONV,CONV_) if(conv==CONV)\ + { \ + if(count==1)\ + ret= (reinterpret_cast<__F_T(CONV,1)>(f))\ + (arguments[0]);\ + else if(count==2)\ + ret= (reinterpret_cast<__F_T(CONV,2)>(f))\ + (arguments[0],arguments[1]);\ + else if(count==3)\ + ret= (reinterpret_cast<__F_T(CONV,3)>(f))\ + (arguments[0],arguments[1],arguments[2]);\ + else if(count==4)\ + ret= (reinterpret_cast<__F_T(CONV,4)>(f))\ + (arguments[0],arguments[1],arguments[2],arguments[3]);\ + else if(count==5)\ + ret= (reinterpret_cast<__F_T(CONV,5)>(f))\ + (arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]);\ + else if(count==6)\ + ret= (reinterpret_cast<__F_T(CONV,6)>(f))\ + (arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);\ + else if(count==7)\ + ret= (reinterpret_cast<__F_T(CONV,7)>(f))\ + (arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6]);\ + } + +#define __FCALLEX(CONV,CONV_) if(conv==CONV)\ + { if(count==1) {__F_T(CONV,1) tmp_F=reinterpret_cast<__F_T(CONV,1)>(f); return tmp_F(arguments[0]);}\ + else if(count==2){__F_T(CONV,2) tmp_F=reinterpret_cast<__F_T(CONV,2)>(f); return tmp_F(arguments[0],arguments[1]);}\ + else if(count==3){__F_T(CONV,3) tmp_F=reinterpret_cast<__F_T(CONV,3)>(f); return tmp_F(arguments[0],arguments[1],arguments[2]);}\ + else if(count==4){__F_T(CONV,4) tmp_F=reinterpret_cast<__F_T(CONV,4)>(f); return tmp_F(arguments[0],arguments[1],arguments[2],arguments[3]);}\ + else if(count==5){__F_T(CONV,5) tmp_F=reinterpret_cast<__F_T(CONV,5)>(f); return tmp_F(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]);}\ + else if(count==6){__F_T(CONV,6) tmp_F=reinterpret_cast<__F_T(CONV,6)>(f); return tmp_F(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);}\ + else if(count==7){__F_T(CONV,7) tmp_F=reinterpret_cast<__F_T(CONV,7)>(f); return tmp_F(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6]);}\ + } + /*else if(count==8)\ + ret= (reinterpret_cast<__F_T(CONV,8)>(f))\ + (arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7]);\ + else if(count==9)\ + ret= (reinterpret_cast(f))\ + (arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8]);\ + else if(count==10)\ + ret= (reinterpret_cast(f))\ + (arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9]);}*/ + + +int FunctionCaller::CallFunction(size_t func_ptr,callconv conv,const vector &arguments) +{ + //nasty nasty code... + int ret=0; + + void* f= reinterpret_cast(func_ptr+base_); + size_t count=arguments.size(); + if(count==0) + return (reinterpret_cast(f))(); //does not matter how we call it... + __F_TYPEDEFS(STD_CALL,__stdcall); + __F_TYPEDEFS(FAST_CALL,__fastcall); + __F_TYPEDEFS(THIS_CALL,__thiscall); + __F_TYPEDEFS(CDECL_CALL,__cdecl); + + __FCALLEX(STD_CALL,__stdcall); + __FCALLEX(FAST_CALL,__fastcall); + __FCALLEX(THIS_CALL,__thiscall); + __FCALLEX(CDECL_CALL,__cdecl); + return ret; +} +#undef __FCALL +#undef __FCALLEX \ No newline at end of file From f003a19e40a2a3905518f44bd13ba12e229b150d Mon Sep 17 00:00:00 2001 From: Warmist Date: Tue, 19 Jul 2011 16:45:54 +0300 Subject: [PATCH 8/8] Functioncalling minilib Signed-off-by: Warmist --- plugins/Dfusion/dfusion.cpp | 14 -------- plugins/Dfusion/include/functioncall.h | 2 ++ plugins/Dfusion/src/functioncall.cpp | 47 +++++++++++++++++++++----- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/plugins/Dfusion/dfusion.cpp b/plugins/Dfusion/dfusion.cpp index e1792ba5f..0cd6883fa 100644 --- a/plugins/Dfusion/dfusion.cpp +++ b/plugins/Dfusion/dfusion.cpp @@ -80,20 +80,6 @@ DFhackCExport command_result plugin_onupdate ( Core * c ) DFhackCExport command_result lua_run (Core * c, vector & parameters) { - //testing part{ - c->Suspend(); - FunctionCaller caller(c->p->getBase()); - std::vector args; - args.push_back((size_t)"Hello world"); - args.push_back(4); - args.push_back(4); - args.push_back(0); - dfprint mprint=(dfprint)(0x27F030+c->p->getBase()); - mprint("Hello world",4,4,0); - caller.CallFunction((0x27F030),FunctionCaller::THIS_CALL,args); - c->Resume(); - return CR_OK; - //}end testing Console &con=c->con; SDL_mutexP(mymutex); lua::state s=lua::glua::Get(); diff --git a/plugins/Dfusion/include/functioncall.h b/plugins/Dfusion/include/functioncall.h index b0cb07038..9f041d1d3 100644 --- a/plugins/Dfusion/include/functioncall.h +++ b/plugins/Dfusion/include/functioncall.h @@ -16,7 +16,9 @@ public: FunctionCaller(size_t base):base_(base){}; int CallFunction(size_t func_ptr,callconv conv,const vector &arguments); + private: + int CallF(size_t count,callconv conv,void* f,const vector &arguments); size_t base_; }; diff --git a/plugins/Dfusion/src/functioncall.cpp b/plugins/Dfusion/src/functioncall.cpp index 085a2e7d2..db78603a7 100644 --- a/plugins/Dfusion/src/functioncall.cpp +++ b/plugins/Dfusion/src/functioncall.cpp @@ -57,25 +57,56 @@ (arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9]);}*/ +int FunctionCaller::CallF(size_t count,callconv conv,void* f,const vector &arguments)//more complex but not more error safe +{ + __F_TYPEDEFS(STD_CALL,__stdcall); + __F_TYPEDEFS(FAST_CALL,__fastcall); + __F_TYPEDEFS(THIS_CALL,__thiscall); + __F_TYPEDEFS(CDECL_CALL,__cdecl); + { + __FCALLEX(STD_CALL,__stdcall); + __FCALLEX(FAST_CALL,__fastcall); + __FCALLEX(THIS_CALL,__thiscall); + __FCALLEX(CDECL_CALL,__cdecl); + } +} int FunctionCaller::CallFunction(size_t func_ptr,callconv conv,const vector &arguments) { //nasty nasty code... - int ret=0; void* f= reinterpret_cast(func_ptr+base_); size_t count=arguments.size(); if(count==0) return (reinterpret_cast(f))(); //does not matter how we call it... + int ret=0; + //typedefs __F_TYPEDEFS(STD_CALL,__stdcall); __F_TYPEDEFS(FAST_CALL,__fastcall); __F_TYPEDEFS(THIS_CALL,__thiscall); __F_TYPEDEFS(CDECL_CALL,__cdecl); - - __FCALLEX(STD_CALL,__stdcall); - __FCALLEX(FAST_CALL,__fastcall); - __FCALLEX(THIS_CALL,__thiscall); - __FCALLEX(CDECL_CALL,__cdecl); - return ret; + //calls + __FCALL(STD_CALL,__stdcall); + __FCALL(FAST_CALL,__fastcall); + __FCALL(THIS_CALL,__thiscall); + __FCALL(CDECL_CALL,__cdecl); + return -1; //incorect type. Should probably throw... + //return CallF(count,conv,f,arguments); + /*//testing part{ worked some time ago..., put where DFHack::Core is accesible + c->Suspend(); + FunctionCaller caller(c->p->getBase()); + std::vector args; + args.push_back((size_t)"Hello world"); + args.push_back(4); + args.push_back(4); + args.push_back(0); + dfprint mprint=(dfprint)(0x27F030+c->p->getBase()); + mprint("Hello world",4,4,0); + //caller.CallFunction((0x27F030),FunctionCaller::THIS_CALL,args); + c->Resume(); + return CR_OK; + //}end testing*/ } #undef __FCALL -#undef __FCALLEX \ No newline at end of file +#undef __FCALLEX +#undef __F_TYPEDEFS +#undef __F_T \ No newline at end of file