Allow plugin exports to be defined in plugins (and looked up when needed)

develop
lethosor 2015-03-07 17:25:35 -05:00
parent 1570af3f4d
commit ea1c9fa0df
2 changed files with 36 additions and 10 deletions

@ -268,7 +268,7 @@ bool Plugin::load(color_ostream &con)
plugin_enable = (command_result (*)(color_ostream &,bool)) LookupPlugin(plug, "plugin_enable"); plugin_enable = (command_result (*)(color_ostream &,bool)) LookupPlugin(plug, "plugin_enable");
plugin_is_enabled = (bool*) LookupPlugin(plug, "plugin_is_enabled"); plugin_is_enabled = (bool*) LookupPlugin(plug, "plugin_is_enabled");
plugin_eval_ruby = (command_result (*)(color_ostream &, const char*)) LookupPlugin(plug, "plugin_eval_ruby"); 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); index_lua(plug);
this->name = *plug_name; this->name = *plug_name;
plugin_lib = plug; plugin_lib = plug;
@ -523,6 +523,16 @@ Plugin::plugin_state Plugin::getState() const
return state; 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) void Plugin::index_lua(DFLibrary *lib)
{ {
if (auto cmdlist = (CommandReg*)LookupPlugin(lib, "plugin_lua_commands")) 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); 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) PluginManager::PluginManager(Core * core)
{ {
cmdlist_mutex = new mutex(); cmdlist_mutex = new mutex();

@ -51,6 +51,7 @@ namespace df
namespace DFHack namespace DFHack
{ {
class Core; class Core;
class PluginExports;
class PluginManager; class PluginManager;
class virtual_identity; class virtual_identity;
class RPCService; class RPCService;
@ -162,12 +163,7 @@ namespace DFHack
command_result invoke(color_ostream &out, const std::string & command, std::vector <std::string> & parameters); command_result invoke(color_ostream &out, const std::string & command, std::vector <std::string> & parameters);
bool can_invoke_hotkey(const std::string & command, df::viewscreen *top ); bool can_invoke_hotkey(const std::string & command, df::viewscreen *top );
plugin_state getState () const; plugin_state getState () const;
void *getExports() PluginExports *getExports();
{
if (plugin_get_exports)
return plugin_get_exports();
return NULL;
};
RPCService *rpc_connect(color_ostream &out); RPCService *rpc_connect(color_ostream &out);
@ -230,8 +226,15 @@ namespace DFHack
command_result (*plugin_enable)(color_ostream &, bool); command_result (*plugin_enable)(color_ostream &, bool);
RPCService* (*plugin_rpcconnect)(color_ostream &); RPCService* (*plugin_rpcconnect)(color_ostream &);
command_result (*plugin_eval_ruby)(color_ostream &, const char*); 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<std::string, void**> bindings;
bool bind(DFLibrary* lib);
}; };
#define PLUGIN_EXPORT_BIND(name) bindings.insert(std::pair<std::string, void**>(#name, (void**)&this->name))
class DFHACK_EXPORT PluginManager class DFHACK_EXPORT PluginManager
{ {
// PRIVATE METHODS // PRIVATE METHODS
@ -292,12 +295,12 @@ namespace DFHack
bool &varname = plugin_is_enabled; bool &varname = plugin_is_enabled;
#define DFHACK_PLUGIN_EXPORTS(clsname) \ #define DFHACK_PLUGIN_EXPORTS(clsname) \
DFhackCExport void* plugin_get_exports() \ DFhackCExport PluginExports* plugin_get_exports() \
{ \ { \
static clsname* instance = NULL; \ static clsname* instance = NULL; \
if (!instance) \ if (!instance) \
instance = new clsname; \ instance = new clsname; \
return (void*)instance; \ return (PluginExports*)instance; \
} }
#define GET_PLUGIN_EXPORTS(plugname, clsname) \ #define GET_PLUGIN_EXPORTS(plugname, clsname) \
(clsname*)DFHack::Core::getInstance().getPluginManager()->getPluginExports(plugname) (clsname*)DFHack::Core::getInstance().getPluginManager()->getPluginExports(plugname)