Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Jonas Kulla | 94c2f2b60e |
|
@ -26,6 +26,7 @@
|
|||
#include "filesystem.h"
|
||||
#include "util.h"
|
||||
#include "debugwriter.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include <ruby.h>
|
||||
#include <ruby/encoding.h>
|
||||
|
@ -290,6 +291,21 @@ static void mriBindingExecute()
|
|||
|
||||
mriBindingInit();
|
||||
|
||||
PluginLoader *pluginLoader;
|
||||
|
||||
try
|
||||
{
|
||||
pluginLoader = new PluginLoader(PLUGIN_MRI);
|
||||
}
|
||||
catch (const Exception &exc)
|
||||
{
|
||||
showMsg(exc.msg);
|
||||
ruby_cleanup(0);
|
||||
shState->rtData().rqTermAck = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string &customScript = shState->rtData().config.customScript;
|
||||
if (!customScript.empty())
|
||||
runCustomScript(customScript.c_str());
|
||||
|
@ -310,7 +326,7 @@ static void mriBindingExecute()
|
|||
}
|
||||
|
||||
ruby_cleanup(0);
|
||||
|
||||
delete pluginLoader;
|
||||
shState->rtData().rqTermAck = true;
|
||||
}
|
||||
|
||||
|
|
7
mkxp.pro
7
mkxp.pro
|
@ -6,6 +6,7 @@ TARGET = mkxp
|
|||
DEPENDPATH += src shader assets
|
||||
INCLUDEPATH += . src
|
||||
LIBS += -lGL
|
||||
QMAKE_LFLAGS += -rdynamic
|
||||
|
||||
CONFIG(release, debug|release): DEFINES += NDEBUG
|
||||
|
||||
|
@ -116,7 +117,8 @@ HEADERS += \
|
|||
src/sharedstate.h \
|
||||
src/al-util.h \
|
||||
src/boost-hash.h \
|
||||
src/debugwriter.h
|
||||
src/debugwriter.h \
|
||||
src/plugin.h
|
||||
|
||||
SOURCES += \
|
||||
src/main.cpp \
|
||||
|
@ -144,7 +146,8 @@ SOURCES += \
|
|||
src/config.cpp \
|
||||
src/tileatlas.cpp \
|
||||
src/perftimer.cpp \
|
||||
src/sharedstate.cpp
|
||||
src/sharedstate.cpp \
|
||||
src/plugin.cpp
|
||||
|
||||
EMBED = \
|
||||
shader/transSimple.frag \
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
#include "plugin.h"
|
||||
#include "debugwriter.h"
|
||||
#include "exception.h"
|
||||
|
||||
#include "binding-util.h"
|
||||
|
||||
static void pluginInit();
|
||||
static void pluginFini();
|
||||
|
||||
Plugin plugin =
|
||||
{
|
||||
pluginInit,
|
||||
pluginFini,
|
||||
PLUGIN_MRI
|
||||
};
|
||||
|
||||
/* Callable from ruby scripts as 'plugin_function' */
|
||||
RB_METHOD(pluginFunction)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
const char *str = 0;
|
||||
rb_get_args(argc, argv, "|z", &str RB_ARG_END);
|
||||
|
||||
Debug() << "Sample plugin function:" << str;
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
void pluginInit()
|
||||
{
|
||||
_rb_define_module_function(rb_mKernel, "plugin_function", pluginFunction);
|
||||
|
||||
Debug() << "Sample plugin inited!";
|
||||
}
|
||||
|
||||
void pluginFini()
|
||||
{
|
||||
Debug() << "Sample plugin finited!";
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
######################################################################
|
||||
# Automatically generated by qmake (2.01a) Fri Jan 3 01:40:45 2014
|
||||
######################################################################
|
||||
|
||||
TEMPLATE = lib
|
||||
QT =
|
||||
TARGET = sample-plugin
|
||||
DEPENDPATH += . ../src ../binding-mri
|
||||
INCLUDEPATH += . ../src ../binding-mri
|
||||
CONFIG += plugin
|
||||
|
||||
unix {
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += ruby-2.1
|
||||
}
|
||||
|
||||
# Input
|
||||
SOURCES += main.cpp
|
|
@ -81,6 +81,7 @@ void Config::read()
|
|||
podesc.add_options()
|
||||
PO_DESC_ALL
|
||||
("RTP", po::value<StringVec>())
|
||||
("plugin", po::value<StringVec>())
|
||||
;
|
||||
|
||||
std::ifstream confFile;
|
||||
|
@ -103,6 +104,7 @@ void Config::read()
|
|||
PO_DESC_ALL;
|
||||
|
||||
GUARD_ALL( rtps = vm["RTP"].as<StringVec>(); );
|
||||
GUARD_ALL( plugins = vm["plugin"].as<StringVec>(); );
|
||||
|
||||
#undef PO_DESC
|
||||
#undef PO_DESC_ALL
|
||||
|
|
|
@ -53,6 +53,8 @@ struct Config
|
|||
std::string customScript;
|
||||
std::vector<std::string> rtps;
|
||||
|
||||
std::vector<std::string> plugins;
|
||||
|
||||
/* Game INI contents */
|
||||
struct {
|
||||
std::string scripts;
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
** plugin.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include "sharedstate.h"
|
||||
#include "config.h"
|
||||
#include "exception.h"
|
||||
|
||||
#include <SDL_loadso.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct LoadedPlugin
|
||||
{
|
||||
void *handle;
|
||||
Plugin *iface;
|
||||
bool inited;
|
||||
};
|
||||
|
||||
struct PluginLoaderPrivate
|
||||
{
|
||||
std::vector<LoadedPlugin> loadedPlugins;
|
||||
|
||||
/* Load so files / lookup interfaces */
|
||||
void loadPlugins(const std::vector<std::string> &plgList,
|
||||
const char *binding)
|
||||
{
|
||||
for (size_t i = 0; i < plgList.size(); ++i)
|
||||
{
|
||||
const std::string &plgName = plgList[i];
|
||||
|
||||
void *handle = SDL_LoadObject(plgName.c_str());
|
||||
|
||||
if (!handle)
|
||||
throw Exception(Exception::SDLError, "%s", SDL_GetError());
|
||||
|
||||
Plugin *iface = static_cast<Plugin*>(SDL_LoadFunction(handle, "plugin"));
|
||||
|
||||
if (!iface)
|
||||
throw Exception(Exception::SDLError, "Error loading plugin '%s' interface: %s",
|
||||
plgName.c_str(), SDL_GetError());
|
||||
|
||||
if (strcmp(binding, iface->binding))
|
||||
throw Exception(Exception::MKXPError, "Plugin '%s' is incompatible with '%s' binding",
|
||||
plgName.c_str(), binding);
|
||||
|
||||
LoadedPlugin loaded;
|
||||
loaded.handle = handle;
|
||||
loaded.iface = iface;
|
||||
loaded.inited = false;
|
||||
|
||||
loadedPlugins.push_back(loaded);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize loaded plugins */
|
||||
void initPlugins()
|
||||
{
|
||||
for (size_t i = 0; i < loadedPlugins.size(); ++i)
|
||||
{
|
||||
LoadedPlugin &plugin = loadedPlugins[i];
|
||||
|
||||
plugin.iface->init();
|
||||
plugin.inited = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finalize loaded plugins */
|
||||
void finiPlugins()
|
||||
{
|
||||
for (size_t i = 0; i < loadedPlugins.size(); ++i)
|
||||
{
|
||||
LoadedPlugin &plugin = loadedPlugins[i];
|
||||
|
||||
if (plugin.inited)
|
||||
plugin.iface->fini();
|
||||
}
|
||||
}
|
||||
|
||||
/* Unload so files */
|
||||
void unloadPlugins()
|
||||
{
|
||||
for (size_t i = 0; i < loadedPlugins.size(); ++i)
|
||||
SDL_UnloadObject(loadedPlugins[i].handle);
|
||||
}
|
||||
};
|
||||
|
||||
PluginLoader::PluginLoader(const char *binding)
|
||||
{
|
||||
p = new PluginLoaderPrivate;
|
||||
|
||||
const std::vector<std::string> &plgList = shState->config().plugins;
|
||||
|
||||
try
|
||||
{
|
||||
p->loadPlugins(plgList, binding);
|
||||
}
|
||||
catch (const Exception &exc)
|
||||
{
|
||||
p->unloadPlugins();
|
||||
delete p;
|
||||
|
||||
throw exc;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
p->initPlugins();
|
||||
}
|
||||
catch (const Exception &exc)
|
||||
{
|
||||
p->finiPlugins();
|
||||
p->unloadPlugins();
|
||||
delete p;
|
||||
|
||||
throw exc;
|
||||
}
|
||||
}
|
||||
|
||||
PluginLoader::~PluginLoader()
|
||||
{
|
||||
p->finiPlugins();
|
||||
p->unloadPlugins();
|
||||
delete p;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
** plugin.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PLUGIN_H
|
||||
#define PLUGIN_H
|
||||
|
||||
/* Note: Plugins are meant to be compiled in unison
|
||||
* with mkxp; there is no API stability whatsoever. */
|
||||
|
||||
/* Use one of these for 'binding' */
|
||||
#define PLUGIN_MRI "mri"
|
||||
#define PLUGIN_MRUBY "mruby"
|
||||
|
||||
/* Interface that plugins implement via global symbol named 'plugin'*/
|
||||
struct Plugin
|
||||
{
|
||||
/* Initialize plugin. May throw 'Exception' instance on error.
|
||||
* The interpreted environment is set up at this point. */
|
||||
void (*init)();
|
||||
|
||||
/* Finalize plugin. The interpreted environment
|
||||
* is already torn down at this point. */
|
||||
void (*fini)();
|
||||
|
||||
/* Binding that this plugin applies to (see above) */
|
||||
const char *binding;
|
||||
};
|
||||
|
||||
|
||||
/* For use in main mkxp */
|
||||
struct PluginLoaderPrivate;
|
||||
|
||||
class PluginLoader
|
||||
{
|
||||
public:
|
||||
PluginLoader(const char *binding);
|
||||
~PluginLoader();
|
||||
|
||||
private:
|
||||
PluginLoaderPrivate *p;
|
||||
};
|
||||
|
||||
#endif // PLUGIN_H
|
Loading…
Reference in New Issue