Creating a plug-in using C++
The APIs for writing plug-ins in C++ are all documented in the
API Reference for C++ (Doxygen). The relevant classes are in the
com::apama::epl:: namespace, provided in the
epl_plugin.hpp header file.
To create a plug-in for EPL in C++, you have to create a class which inherits from EPLPlugin. EPLPlugin is a class template with one template parameter, which should be the derived class which implements your plug-in. Your class must provide a zero-argument constructor and a static initialize method which takes a base_plugin_t::method_data_t & argument. For example:
class MyPlugin: public EPLPlugin<MyPlugin>
{
public:
MyPlugin(): base_plugin_t("MyPlugin")
{}
static void initialize(base_plugin_t::method_data_t &md)
{
}
};
base_plugin_t is a convenience typedef to the EPLPlugin base class. The base class constructor takes a single argument of descriptive string which is used for logging purposes. The base class provides two members to derived classes:
Member | Description |
logger | |
static getCorrelator() | Returns a CorrelatorInterface & which can be used to make various callbacks into the correlator. |
A single instance of your class is created when the plug-in is loaded. Functions which you want to expose to EPL are member functions on that instance. To export a function to EPL, you need to declare a member function on the class with argument and return types which can be translated into EPL (see
Method signatures). The function is exported into EPL by calling
registerMethod on the
method_data_t passed to
initialize:
static void initialize(base_plugin_t::method_data_t &md)
{
md.registerMethod<decltype(&MyPlugin::doSomething),
&MyPlugin::doSomething>("doSomething");
}
void doSomething(int64_t arg1, double arg2)
{
// ...
}
registerMethod is templated over the following:
the type of the function to export, which can be shortcut with
decltype() as shown above, and
the function to export.
registerMethod takes a mandatory argument, which is the name of the function in EPL, and two optional arguments.
If the method signatures in EPL are not deducible from the C++ arguments, then you must provide the EPL type signature of the method.
There is a final Boolean parameter, which defaults to
true. It should be
true if the plug-in may block (see
Blocking behavior of plug-ins) and
false otherwise.
md.registerMethod<decltype(&MyPlugin::simpleSignature),
&MyPlugin::simpleSignature>("simpleMethod");
md.registerMethod<decltype(&MyPlugin::simpleSignatureNonBlocking),
&MyPlugin::simpleSignatureNonBlocking>("nonBlockingMethod", false);
md.registerMethod<decltype(&MyPlugin::complexSignature),
&MyPlugin::complexSignature>("complexMethod",
"action<sequence<string>, integer> returns string");
Finally, to export the plug-in, you have to use the APAMA_DECLARE_EPL_PLUGIN macro. If your class is in a namespace, then you have to put the macro inside the same namespace and give it the class name without qualification as an argument:
APAMA_DECLARE_EPL_PLUGIN(MyClass)
Plug-ins are loaded into the correlator by using the import statement in the monitor or event which wants to use the plug-in. The argument is the name of the library which contains the plug-in.
import "MyPlugin" as plugin;
Complete simple example
This example implements a plug-in which simply keeps a single global count.
#include <epl_plugin.hpp>
using namespace com::apama::epl;
class CountPlugin: public EPLPlugin<MyPlugin>
{
public:
CountPlugin()
: base_plugin_t("CountPlugin"),
count(0)
{}
static void initialize(base_plugin_t::method_data_t &md)
{
md.registerMethod<decltype(&CountPlugin::incrementCount),
&CountPlugin::incrementCount>("increment");
md.registerMethod<decltype(&CountPlugin::getCount),
&CountPlugin::getCount>("getCount");
}
int64_t getCount() { return count; }
void incrementCount(int64_t n) { count += n; }
// Note that this is not thread-safe; a real plug-in would
// want to use some synchronization here
private:
int64_t count;
};
monitor foo
{
import "PluginLibrary" as counter;
action onload()
{
on all A() {
counter.increment(1);
print "Current count: "+counter.getCount().toString();
}
}
}