Add experimental plugin system
Plugins define the interface specified in plugin.h and have full access to any functions exposed in mkxp. Specify plugins to be loaded in the config file via 'plugin=/path/to/plugin.so' lines. A sample plugin for the MRI binding is provided.
This commit is contained in:
		
							parent
							
								
									3daf805350
								
							
						
					
					
						commit
						94c2f2b60e
					
				
					 8 changed files with 290 additions and 3 deletions
				
			
		| 
						 | 
					@ -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 \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										41
									
								
								sample-plugin/main.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								sample-plugin/main.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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!";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								sample-plugin/sample-plugin.pro
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								sample-plugin/sample-plugin.pro
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										144
									
								
								src/plugin.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								src/plugin.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										61
									
								
								src/plugin.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/plugin.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue