Writing a file I/O plugin is as simple as subclassing the agfio_plugin class, which declares three virtual methods: one load() and two overloaded store()'s. So in general, the steps for writing a file I/O plugin are as follows:
In this example, we create a toy plugin called MyFormat.
MyFormat.h | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#ifndef _MYFORMAT_H_ #define _MYFORMAT_H_ #include <ag/agfio_plugin.h> class MyFormat: public agfio_plugin { public: virtual list<AGId> load(const string& filename, const Id& id = "", map<string,string>* signalInfo = NULL, map<string,string>* options = NULL) throw (agfio::LoadError); virtual string store(const string& filename, const Id& id = "", map<string,string>* options = NULL) throw (agfio::StoreError); }; AGFIO_PLUGIN(MyFormat); #endif |
Line 4
The agfio_plugin class is defined in
ag/agfio_plugin.h, so you have to
include that.
Line 6
The plugin name (=class name) is MyFormat, and it's a
subclass of agfio_plugin.
Lines 9-20
The load() and one of store()'s are
overridden. If not overridden, the default behavior of these methods is
to throw an exception saying that the method is not supported. About the
exceptions thrown:
load() throws
agfio::LoadError
store()'s throw
agfio::StoreError.
Another important thing to keep in mind: When your load/store routines encounter an error that can't be handled, make them throw agfio::LoadError (for load()) or agfio::StoreError (for store()'s) with some useful error message rather than exiting the program. These exceptions are propagated through the AGLIB core to the user applications. The applications can do something for those exceptions, if they decide to handle them.
Line 23
AGFIO_PLUGIN() is a macro that sets up some internal functions
that are used to load/unload the plugin. The argument is the name of the
plugin class. This line can appear in other files than header files, but
it should be evaluted exactly once in the entire source files. For example,
suppose that MyFormat-load.cc implemented the load(), and
MyFormat-store.cc implemented the store(). Both of them included
MyFormat.h. This is an error, because the AGFIO_PLUGIN(MyFormat) is
evaluated twice: once in MyFormat-load.cc and once in MyFormat-store.cc.
The solution in this case is to remove that line from the header and put it
in one of the .cc files.
MyFormat.cc | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include "MyFormat.h" list<AGId> MyFormat::load(const string& filename, const Id& id, map<string,string>* signalInfo, map<string,string>* options) throw (agfio::LoadError) { cout << "MyFormat::load" << endl; cout << "filename=" << filename << endl; list<AGId> a; return a; } string MyFormat::store(const string& filename, const Id& id, map<string,string>* options) throw (agfio::StoreError) { cout << "MyFormat::store" << endl; cout << "filename=" << filename << endl; cout << "id=" << id << endl; return ""; } |
Lines 3-14
Implement load() method. It just prints a string and returns an
empty list.
Lines 16-26
Implement store() method. It just prints a string and returns an
empty string.
Once you finish your plugin class, the next step is compilation. Here is an example:
g++ -shared -o agfio_plugin_MyFormat.so MyPlugin.cc -lagGcc was used for the compiler in this example. '-shared' tells g++ to make a shared object. Other compilers may have a different command line option for this. The point is that you have to make it a shared object.
If there is no error in the source code, g++ will generate agfio_plugin_MyFormat.so as a result. This is the final result of your toy file I/O plugin. Different platforms have different extensions for shared objects. For instance, Windows systems use .dll, so in those systems, you have to name your plugin like this: agfio_plugin_MyFormat.dll. The prefix, agfio_plugin_ is significant. You always have to prefix your plugin (the shared object) with it. Otherwise AGLIB won't be able to find your plugin.
To see if the plugin is working, you can compile and run the following test program. When you run the program, make sure that the directory where your plugin is located is in the system's search path (check LD_LIBRARY_PATH for UNIX-like systems or PATH for Windows systems). If the plugin directory is not in the system's search path, AGLIB can't load it.
test.cc | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <iostream> #include <ag/AGAPI.h> using namespace std; int main() { cout << "----------" << endl; cout << "loading..." << endl; Load("MyFormat", "inputfile.txt"); cout << "----------" << endl; cout << "storing..." << endl; Store("MyFormat", "outputfile.txt", "Test:123"); } |