From ea1c9fa0dfb42e52b3213d535f2fb5bc53d7499e Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 7 Mar 2015 17:25:35 -0500 Subject: [PATCH] Allow plugin exports to be defined in plugins (and looked up when needed) --- library/PluginManager.cpp | 25 ++++++++++++++++++++++++- library/include/PluginManager.h | 21 ++++++++++++--------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp index 50410f9a0..01b5ea5da 100644 --- a/library/PluginManager.cpp +++ b/library/PluginManager.cpp @@ -268,7 +268,7 @@ bool Plugin::load(color_ostream &con) plugin_enable = (command_result (*)(color_ostream &,bool)) LookupPlugin(plug, "plugin_enable"); plugin_is_enabled = (bool*) LookupPlugin(plug, "plugin_is_enabled"); plugin_eval_ruby = (command_result (*)(color_ostream &, const char*)) LookupPlugin(plug, "plugin_eval_ruby"); - plugin_get_exports = (void* (*)(void)) LookupPlugin(plug, "plugin_get_exports"); + plugin_get_exports = (PluginExports* (*)(void)) LookupPlugin(plug, "plugin_get_exports"); index_lua(plug); this->name = *plug_name; plugin_lib = plug; @@ -523,6 +523,16 @@ Plugin::plugin_state Plugin::getState() const return state; } +PluginExports *Plugin::getExports() +{ + if (!plugin_get_exports) + return NULL; + PluginExports *exports = plugin_get_exports(); + if (!exports->bind(plugin_lib)) + return NULL; + return exports; +}; + void Plugin::index_lua(DFLibrary *lib) { if (auto cmdlist = (CommandReg*)LookupPlugin(lib, "plugin_lua_commands")) @@ -695,6 +705,19 @@ void Plugin::push_function(lua_State *state, LuaFunction *fn) lua_pushcclosure(state, lua_fun_wrapper, 4); } +bool PluginExports::bind(DFLibrary *lib) +{ + for (auto it = bindings.begin(); it != bindings.end(); ++it) + { + std::string name = it->first; + void** dest = it->second; + *dest = LookupPlugin(lib, name.c_str()); + if (!*dest) + return false; + } + return true; +} + PluginManager::PluginManager(Core * core) { cmdlist_mutex = new mutex(); diff --git a/library/include/PluginManager.h b/library/include/PluginManager.h index 09030664a..a8f93b431 100644 --- a/library/include/PluginManager.h +++ b/library/include/PluginManager.h @@ -51,6 +51,7 @@ namespace df namespace DFHack { class Core; + class PluginExports; class PluginManager; class virtual_identity; class RPCService; @@ -162,12 +163,7 @@ namespace DFHack command_result invoke(color_ostream &out, const std::string & command, std::vector & parameters); bool can_invoke_hotkey(const std::string & command, df::viewscreen *top ); plugin_state getState () const; - void *getExports() - { - if (plugin_get_exports) - return plugin_get_exports(); - return NULL; - }; + PluginExports *getExports(); RPCService *rpc_connect(color_ostream &out); @@ -230,8 +226,15 @@ namespace DFHack command_result (*plugin_enable)(color_ostream &, bool); RPCService* (*plugin_rpcconnect)(color_ostream &); command_result (*plugin_eval_ruby)(color_ostream &, const char*); - void* (*plugin_get_exports)(void); + PluginExports* (*plugin_get_exports)(void); + }; + class DFHACK_EXPORT PluginExports { + protected: + friend class Plugin; + std::map bindings; + bool bind(DFLibrary* lib); }; + #define PLUGIN_EXPORT_BIND(name) bindings.insert(std::pair(#name, (void**)&this->name)) class DFHACK_EXPORT PluginManager { // PRIVATE METHODS @@ -292,12 +295,12 @@ namespace DFHack bool &varname = plugin_is_enabled; #define DFHACK_PLUGIN_EXPORTS(clsname) \ - DFhackCExport void* plugin_get_exports() \ + DFhackCExport PluginExports* plugin_get_exports() \ { \ static clsname* instance = NULL; \ if (!instance) \ instance = new clsname; \ - return (void*)instance; \ + return (PluginExports*)instance; \ } #define GET_PLUGIN_EXPORTS(plugname, clsname) \ (clsname*)DFHack::Core::getInstance().getPluginManager()->getPluginExports(plugname)