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_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();

@ -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 <std::string> & 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<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
{
// 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)