summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMoritz Eberl <moritz@semiodesk.com>2016-04-11 14:53:05 +0000
committerMoritz Eberl <moritz@semiodesk.com>2016-04-11 14:53:05 +0000
commit58a5565b6d840af2e6a0e74c1554018f75d689b0 (patch)
treebe65d1a9c02dc80d6508ed315950eac33232a34d /src
parentFix node size regression and add ctrlResize property for multiple use. (diff)
downloadinkscape-58a5565b6d840af2e6a0e74c1554018f75d689b0.tar.gz
inkscape-58a5565b6d840af2e6a0e74c1554018f75d689b0.zip
Added a mechanism to load c++ extensions dynamically.
(bzr r14761.1.1)
Diffstat (limited to 'src')
-rw-r--r--src/extension/CMakeLists.txt2
-rw-r--r--src/extension/Makefile_insert2
-rw-r--r--src/extension/dependency.cpp12
-rw-r--r--src/extension/dependency.h1
-rw-r--r--src/extension/loader.cpp103
-rw-r--r--src/extension/loader.h73
-rw-r--r--src/extension/system.cpp17
7 files changed, 202 insertions, 8 deletions
diff --git a/src/extension/CMakeLists.txt b/src/extension/CMakeLists.txt
index 21e652563..238e8d3df 100644
--- a/src/extension/CMakeLists.txt
+++ b/src/extension/CMakeLists.txt
@@ -14,6 +14,7 @@ set(extension_SRC
print.cpp
system.cpp
timer.cpp
+ loader.cpp
implementation/implementation.cpp
implementation/xslt.cpp
@@ -90,6 +91,7 @@ set(extension_SRC
print.h
system.h
timer.h
+ loader.h
implementation/implementation.h
implementation/script.h
diff --git a/src/extension/Makefile_insert b/src/extension/Makefile_insert
index 4e75de13a..fb9713904 100644
--- a/src/extension/Makefile_insert
+++ b/src/extension/Makefile_insert
@@ -13,6 +13,8 @@ ink_common_sources += \
extension/execution-env.h \
extension/init.cpp \
extension/init.h \
+ extension/loader.h \
+ extension/loader.cpp \
extension/param/parameter.h \
extension/param/parameter.cpp \
extension/param/notebook.h \
diff --git a/src/extension/dependency.cpp b/src/extension/dependency.cpp
index e46b6fbd2..712a9068d 100644
--- a/src/extension/dependency.cpp
+++ b/src/extension/dependency.cpp
@@ -235,6 +235,18 @@ bool Dependency::check (void) const
}
/**
+ \brief Accessor to the name attribute.
+ \return A string containing the name of the dependency.
+
+ Returns the name of the dependency as found in the configuration file.
+
+*/
+const gchar* Dependency::getName()
+{
+ return _string;
+}
+
+/**
\brief Print out a dependency to a string.
*/
std::ostream &
diff --git a/src/extension/dependency.h b/src/extension/dependency.h
index 829912dc3..5d0a4844e 100644
--- a/src/extension/dependency.h
+++ b/src/extension/dependency.h
@@ -58,6 +58,7 @@ public:
Dependency (Inkscape::XML::Node * in_repr);
virtual ~Dependency (void);
bool check (void) const;
+ const gchar* getName();
Glib::ustring &get_help (void) const;
Glib::ustring &get_link (void) const;
diff --git a/src/extension/loader.cpp b/src/extension/loader.cpp
new file mode 100644
index 000000000..df193a051
--- /dev/null
+++ b/src/extension/loader.cpp
@@ -0,0 +1,103 @@
+/*
+ * Loader for external plug-ins.
+ *
+ * Authors:
+ * Moritz Eberl <moritz@semiodesk.com>
+ *
+ * Copyright (C) 2016 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "loader.h"
+#include "system.h"
+#include <exception>
+#include <string.h>
+#include "dependency.h"
+
+namespace Inkscape {
+namespace Extension {
+
+typedef Implementation::Implementation *(*_getImplementation)(void);
+
+bool Loader::LoadDependency(Dependency *dep)
+{
+ GModule *module = NULL;
+ module = g_module_open(dep->getName(), (GModuleFlags)0);
+ if (module == NULL) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * @brief Load the actual implementation of a plugin supplied by the plugin.
+ * @param doc The xml representation of the INX extension configuration.
+ * @return The implementation of the extension loaded from the plugin.
+ */
+Implementation::Implementation *Loader::LoadImplementation(Inkscape::XML::Document *doc)
+{
+ try {
+ Inkscape::XML::Node *repr = doc->root();
+ Inkscape::XML::Node *child_repr = repr->firstChild();
+ while (child_repr != NULL) {
+ char const *chname = child_repr->name();
+ if (!strncmp(chname, INKSCAPE_EXTENSION_NS_NC, strlen(INKSCAPE_EXTENSION_NS_NC))) {
+ chname += strlen(INKSCAPE_EXTENSION_NS);
+ }
+
+ if (!strcmp(chname, "dependency")) {
+ Dependency dep = Dependency(child_repr);
+ bool success = LoadDependency(&dep);
+ if( !success ){
+ const char *res = g_module_error();
+ g_warning("Unable to load dependency %s of plugin %s.\nDetails: %s\n", dep.getName(), res);
+ return NULL;
+ }
+ }
+
+ if (!strcmp(chname, "plugin")) {
+ if (const gchar *name = child_repr->attribute("name")) {
+ GModule *module = NULL;
+ _getImplementation GetImplementation = NULL;
+ gchar *path = g_build_filename(_baseDirectory, name, (char *) NULL);
+ module = g_module_open(path, G_MODULE_BIND_LOCAL);
+ g_free(path);
+ if (module == NULL) {
+ const char *res = g_module_error();
+ g_warning("Unable to load extension %s.\nDetails: %s\n", name, res);
+ return NULL;
+ }
+
+ if (g_module_symbol(module, "GetImplementation", (gpointer *) &GetImplementation) == FALSE) {
+ const char *res = g_module_error();
+ g_warning("Unable to load extension %s.\nDetails: %s\n", name, res);
+ return NULL;
+ }
+
+ Implementation::Implementation *i = GetImplementation();
+ return i;
+ }
+ }
+
+ child_repr = child_repr->next();
+ }
+ } catch (std::exception &e) {
+ g_warning("Unable to load extension.");
+ }
+ return NULL;
+}
+
+} // namespace Extension
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace .0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99: \ No newline at end of file
diff --git a/src/extension/loader.h b/src/extension/loader.h
new file mode 100644
index 000000000..c09260f72
--- /dev/null
+++ b/src/extension/loader.h
@@ -0,0 +1,73 @@
+/** @file
+ * Loader for external plug-ins.
+ *//*
+ *
+ * Authors:
+ * Moritz Eberl <moritz@semiodesk.com>
+ *
+ * Copyright (C) 2016 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_EXTENSION_LOADER_H_
+#define INKSCAPE_EXTENSION_LOADER_H_
+
+#include "extension.h"
+#include "implementation/implementation.h"
+#include <gmodule.h>
+
+
+namespace Inkscape {
+namespace Extension {
+
+/** This class contains the mechanism to load c++ plugins dynamically.
+*/
+class Loader {
+
+public:
+ /**
+ * Sets a base directory where to look for the actual plugin to load.
+ *
+ * @param dir is the path where the plugin should be loaded from.
+ */
+ void setBaseDirectory(const gchar *dir) {
+ _baseDirectory = dir;
+ }
+
+ /**
+ * Loads plugin dependencies which are needed for the plugin to load.
+ *
+ * @param dep
+ */
+ bool LoadDependency(Dependency *dep);
+
+ /**
+ * Load the actual implementation of a plugin supplied by the plugin.
+ *
+ * @param doc The xml representation of the INX extension configuration.
+ * @return The implementation of the extension loaded from the plugin.
+ */
+ Implementation::Implementation *LoadImplementation(Inkscape::XML::Document *doc);
+
+private:
+ const gchar *_baseDirectory; /**< The base directory to load a plugin from */
+
+
+};
+
+} // namespace Extension
+} // namespace Inkscape */
+
+#endif // _LOADER_H_
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace .0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99: \ No newline at end of file
diff --git a/src/extension/system.cpp b/src/extension/system.cpp
index 6a95717f2..5a77ac28e 100644
--- a/src/extension/system.cpp
+++ b/src/extension/system.cpp
@@ -39,6 +39,7 @@
#include "io/sys.h"
#include "inkscape.h"
#include "document-undo.h"
+#include "loader.h"
namespace Inkscape {
@@ -426,7 +427,7 @@ build_from_reprdoc(Inkscape::XML::Document *doc, Implementation::Implementation
enum {
MODULE_EXTENSION,
MODULE_XSLT,
- /* MODULE_PLUGIN, */
+ MODULE_PLUGIN,
MODULE_UNKNOWN_IMP
} module_implementation_type = MODULE_UNKNOWN_IMP;
enum {
@@ -465,10 +466,8 @@ build_from_reprdoc(Inkscape::XML::Document *doc, Implementation::Implementation
module_implementation_type = MODULE_EXTENSION;
} else if (!strcmp(element_name, INKSCAPE_EXTENSION_NS "xslt")) {
module_implementation_type = MODULE_XSLT;
-#if 0
- } else if (!strcmp(element_name, "plugin")) {
+ } else if (!strcmp(element_name, INKSCAPE_EXTENSION_NS "plugin")) {
module_implementation_type = MODULE_PLUGIN;
-#endif
}
//Inkscape::XML::Node *old_repr = child_repr;
@@ -489,13 +488,15 @@ build_from_reprdoc(Inkscape::XML::Document *doc, Implementation::Implementation
imp = static_cast<Implementation::Implementation *>(xslt);
break;
}
-#if 0
case MODULE_PLUGIN: {
- Implementation::Plugin *plugin = new Implementation::Plugin();
- imp = static_cast<Implementation::Implementation *>(plugin);
+ Inkscape::Extension::Loader loader = Inkscape::Extension::Loader();
+ loader.setBaseDirectory ( Inkscape::Application::profile_path("extensions"));
+ imp = loader.LoadImplementation(doc);
+ if( imp != NULL) {
+ return new Extension(repr, imp);
+ }
break;
}
-#endif
default: {
imp = NULL;
break;