Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Jonas Kulla | 94c2f2b60e |
|
@ -26,6 +26,7 @@
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "debugwriter.h"
|
#include "debugwriter.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
|
||||||
#include <ruby.h>
|
#include <ruby.h>
|
||||||
#include <ruby/encoding.h>
|
#include <ruby/encoding.h>
|
||||||
|
@ -290,6 +291,21 @@ static void mriBindingExecute()
|
||||||
|
|
||||||
mriBindingInit();
|
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;
|
std::string &customScript = shState->rtData().config.customScript;
|
||||||
if (!customScript.empty())
|
if (!customScript.empty())
|
||||||
runCustomScript(customScript.c_str());
|
runCustomScript(customScript.c_str());
|
||||||
|
@ -310,7 +326,7 @@ static void mriBindingExecute()
|
||||||
}
|
}
|
||||||
|
|
||||||
ruby_cleanup(0);
|
ruby_cleanup(0);
|
||||||
|
delete pluginLoader;
|
||||||
shState->rtData().rqTermAck = true;
|
shState->rtData().rqTermAck = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
mkxp.pro
7
mkxp.pro
|
@ -6,6 +6,7 @@ TARGET = mkxp
|
||||||
DEPENDPATH += src shader assets
|
DEPENDPATH += src shader assets
|
||||||
INCLUDEPATH += . src
|
INCLUDEPATH += . src
|
||||||
LIBS += -lGL
|
LIBS += -lGL
|
||||||
|
QMAKE_LFLAGS += -rdynamic
|
||||||
|
|
||||||
CONFIG(release, debug|release): DEFINES += NDEBUG
|
CONFIG(release, debug|release): DEFINES += NDEBUG
|
||||||
|
|
||||||
|
@ -116,7 +117,8 @@ HEADERS += \
|
||||||
src/sharedstate.h \
|
src/sharedstate.h \
|
||||||
src/al-util.h \
|
src/al-util.h \
|
||||||
src/boost-hash.h \
|
src/boost-hash.h \
|
||||||
src/debugwriter.h
|
src/debugwriter.h \
|
||||||
|
src/plugin.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
src/main.cpp \
|
src/main.cpp \
|
||||||
|
@ -144,7 +146,8 @@ SOURCES += \
|
||||||
src/config.cpp \
|
src/config.cpp \
|
||||||
src/tileatlas.cpp \
|
src/tileatlas.cpp \
|
||||||
src/perftimer.cpp \
|
src/perftimer.cpp \
|
||||||
src/sharedstate.cpp
|
src/sharedstate.cpp \
|
||||||
|
src/plugin.cpp
|
||||||
|
|
||||||
EMBED = \
|
EMBED = \
|
||||||
shader/transSimple.frag \
|
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()
|
podesc.add_options()
|
||||||
PO_DESC_ALL
|
PO_DESC_ALL
|
||||||
("RTP", po::value<StringVec>())
|
("RTP", po::value<StringVec>())
|
||||||
|
("plugin", po::value<StringVec>())
|
||||||
;
|
;
|
||||||
|
|
||||||
std::ifstream confFile;
|
std::ifstream confFile;
|
||||||
|
@ -103,6 +104,7 @@ void Config::read()
|
||||||
PO_DESC_ALL;
|
PO_DESC_ALL;
|
||||||
|
|
||||||
GUARD_ALL( rtps = vm["RTP"].as<StringVec>(); );
|
GUARD_ALL( rtps = vm["RTP"].as<StringVec>(); );
|
||||||
|
GUARD_ALL( plugins = vm["plugin"].as<StringVec>(); );
|
||||||
|
|
||||||
#undef PO_DESC
|
#undef PO_DESC
|
||||||
#undef PO_DESC_ALL
|
#undef PO_DESC_ALL
|
||||||
|
|
|
@ -53,6 +53,8 @@ struct Config
|
||||||
std::string customScript;
|
std::string customScript;
|
||||||
std::vector<std::string> rtps;
|
std::vector<std::string> rtps;
|
||||||
|
|
||||||
|
std::vector<std::string> plugins;
|
||||||
|
|
||||||
/* Game INI contents */
|
/* Game INI contents */
|
||||||
struct {
|
struct {
|
||||||
std::string scripts;
|
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