Main  /  Edit version 1  /  Edit version 2  /   /  Users Area

Difference "Plugin Architecture" ver. 1 versus ver. 2

Content:

<!--toc-->
## Overview
CPPCMS will have a full native support for plugins in the upcoming version 1.2 which will be released later this year (2012).
Meanwhile, CPPCMS 1.0 arleady has all the basics in place to support plugins. Templates are already fully pluggable (load a shared object and the template is ready to use). Also there is a new booster::shared_object class which allows to load dynamic libraries easily.
However, depending on the architecture of your application, the exact solution to adopt may vary. In the following sections, we'll explore different case scenarios. If anything here is not clear, please ask on the mailing list and come back here to appropriately edit this page.
## Template plugged via a shared object.
Each template shared object has a global constructor and destructor. Once a shared object is loaded, the constructor is called and it registers itself in cppcms::views::pool singleton and become visible for everybody. When it is unloaded it is unregistered via the global destructor and can't be used any more. It is simple and transparent semantics.
If a plugin is linked with the template code it would loads its own template:
libmy_plugin.so
my_application.cpp:
// my code
{
...
render("my_plugin_skin","some_view",some_content);
}
my_view.cpp <- my_view.tmpl
// this code is auto-generated
namespace {
struct loader {
loader() { cppcms::views::pool::instance().add(my_skin_generator()); }
~loader() { cppcms::views::pool::instance().remove(my_skin_generator());}
} loader_instance;
}
So once you load the shared object, loader::loader() is executed and registers a view and when you unload the shared object loader::~loader() unregisters it.
Make sure that each template has its own skin name.
## Templates with own plugin framework
If you have implemented your own plugin framework, here are two methods to allow plugins to define their own templates for the content they create, to be integrated in the page generated by the main application.
### Using streams
The core application defines the layout for the whole page:
<% skin basic_skin %>
<% view basic_view uses content::basic_content %>
<html>
...
<body>
...
<!--- aux part-->
<% foreach p in plugings %>
<% item %><%= p.rendered_aux_html_content | raw %><% end %>
<% end %>
...
<!--- Main part-->
<% foreach p in plugings %>
<% item %>
<div id="plugin_<%=p.id %>" >
<%= p.rendered_main_html_content | raw %>
</div>
<% end %>
<% end %>
...
</body>
<% end view %>
...
<% end skin %>
Each plugin defines the templates for their own content:
<% skin plugin_a %>
<% view main_html uses plugin_a_content::some_content_b %>
<% template render() %>
<!-- Notice render function -->
some plugin specific html
that does something it needs
<% end template %>
<% view aux_html uses plugin_a_content::some_content_a %>
<% template render() %>
<!-- Notice render function -->
some plugin specific html
that does something it needs
<% end template %>
<% end view %>
<% end skin %>
Let's say that our plugin should provide the following API:
class plugin {
public:
virtual std::string main_html(cppcms::applicatin *app) = 0;
virtual std::string aux_html(cppcms::application *app) = 0;
};
The content of each plugin is rendered as follows:
// main_application.cpp
content::basic_content c;
// prepare c
...
// render plugins
for(int i=0;i<loaded_plugins.size();i++) {
c.plugins[i].rendered_main_html_content = loaded_plugins[i]->main_html(this);
c.plugins[i].rendered_aux_html_content = loaded_plugins[i]->aux_html(this);
}
render("basic_skin","basic_view",c);
On the plugin side, it looks like this:
std::string main_html(cppcms::applicatin *app)
{
plugin_a_content::some_content_b c;
...
std::ostringstream buf;
app->render("plugin_a","main_html",c,buf);
return buf.str();
}
std::string aux_html(cppcms::applicatin *app)
{
plugin_a_content::some_content_a c;
...
std::ostringstream buf;
app->render("plugin_a","aux_html",c,buf);
return buf.str();
}
### With the command render
Since CPPCMS 0.99.12, there is the command <% render ... %> See [Rendering other views](wikipp/en/page/cppcms_1x_templates_comm#Rendering.other.views).
The core application defines the layout for the whole page:
<% skin basic_skin %>
<% view basic_view uses content::basic_content %>
<html>
...
<body>
...
<!--- aux part-->
<% foreach p in plugings %>
<% item %><% render p->name(), "aux_html" with p->aux_html_content() %><% end %>
<% end %>
...
<!--- Main part-->
<% foreach p in plugings %>
<% item %>
<div id="plugin_<%=p->id() %>" >
<% render p->name(), "main_html" with p->main_html_content() %>
</div>
<% end %>
<% end %>
...
</body>
<% end view %>
...
<% end skin %>
Where p is a pointer to the plugin object.
The plugin's template would be implemented like in the previous section. See above.
Let's say that our plugin should provide the following api:
class plugin {
public:
virtual void prepare() = 0;
virtual cppcms::base_content &main_html_content() = 0;
virtual cppcms::base_content &aux_html_content() = 0;
virtua std::string name() = 0;
};
The content of each plugin is rendered as follows:
basic_content {
...
// pointers to plugins
std::vector<plugin *> plugins;
}
main_application.cpp:
content::basic_content c;
// prepare c
...
for(p in plugins)
p->prepare();
render("basic_skin","basic_view",c);
On the plugin side:
class my_plugin : public plugin {
public:
virtual void prepare()
{
... setup main_ and aux_...
}
virtual std::string name() { return "plugin_a"; }
virtual cppcms::basic_content &main_html_content() { return main_; }
virtual cppcms::basic_content &aux_html_content() { return aux_; }
private:
plugin_a_content::some_content_b aux_;
plugin_a_content::some_content_a main_;
};
std::string main_html(cppcms::applicatin *app)
{
plugin_a_content::some_content_b c;
...
std::ostringstream buf;
app->render("plugin_a","main_html",c,buf);
return buf.str();
}
std::string aux_html(cppcms::applicatin *app)
{
plugin_a_content::some_content_a c;
...
std::ostringstream buf;
app->render("plugin_a","aux_html",c,buf);
return buf.str();
}
### Variation
Variation on the above, according to the needs of your application.
Plugin definition:
plugin {
void render_main(cppcms::application &);
void render_aux(cppcms::application &);
}
Where the plugin is executed like:
render_main(cppcms::application &app)
{
app.render("plugin_a","main_html",my_content);
}
And the template looks like:
<% foreach p in plugins %>
<% item %>
<% c++ p->render_main(content.app()); %>
<% end item %>
<% end foreach %>

About

CppCMS is a web development framework for performance demanding applications.

Support This Project

SourceForge.net Logo

Поддержать проект

CppCMS needs You


Navigation

Main Page


Valid CSS | Valid XHTML 1.0