今回は、POCOでのクラスローディングの実装例を詳解します。
まず、参考情報のポインタを示します。
http://pocoproject.org/slides/120-SharedLibraries.pdf
さて、このクラスローディングはPOCO独自の機能で、シェアドライブラリからプログラム実行時にクラスを動的生成することができます。
シェアドライブラリを追加・変更することで、プログラムの振る舞いを変更できますので、主な用途としてはプラグインが挙げられます。
クラスローディングのサンプルコードは、シェアドライブラリのコードとクラスローディングするコードの2つに分かれます。
シェアドライブラリ;TestPlugin.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#ifndef TestPlugin_INCLUDED
#define TestPlugin_INCLUDED
#include "Poco/Foundation.h"
class TestPlugin
{
public:
TestPlugin();
virtual ~TestPlugin();
virtual std::string name() const = 0;
};
#endif // TestPlugin_INCLUDED |
シェアドライブラリ;TestPlugin.cpp
1 2 3 4 5 6 7 8 9 |
#include "TestPlugin.h"
TestPlugin::TestPlugin()
{
}
TestPlugin::~TestPlugin()
{
} |
シェアドライブラリ;TestLibrary.cpp
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 27 28 29 30 31 32 33 34 35 36 37 |
#include "TestPlugin.h"
#include "Poco/ClassLibrary.h"
#include <iostream>
class PluginA: public TestPlugin
{
public:
PluginA()
{
}
~PluginA()
{
}
std::string name() const
{
return "PluginA";
}
};
POCO_BEGIN_MANIFEST(TestPlugin)
POCO_EXPORT_CLASS(PluginA)
POCO_END_MANIFEST
void pocoInitializeLibrary()
{
std::cout << "TestLibrary initializing" << std::endl;
}
void pocoUninitializeLibrary()
{
std::cout << "TestLibrary uninitialzing" << std::endl;
} |
実行コード:ClassLoaderSample.cpp
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
#include "Poco/ClassLoader.h"
#include "Poco/Manifest.h"
#include "Poco/Exception.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Util/AbstractConfiguration.h"
#include <iostream>
#include "TestPlugin.h"
using Poco::ClassLoader;
using Poco::Manifest;
using Poco::SharedLibrary;
using Poco::AbstractMetaObject;
using Poco::NotFoundException;
using Poco::InvalidAccessException;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
using Poco::Util::AbstractConfiguration;
using Poco::Util::OptionCallback;
class ClassLoaderSample: public Application
/// This sample demonstrates some of the features of the Poco::ClassLoader class.
{
public:
ClassLoaderSample(): _helpRequested(false)
{
}
protected:
void initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
Application::initialize(self);
// add your own initialization code here
}
void uninitialize()
{
// add your own uninitialization code here
Application::uninitialize();
}
void reinitialize(Application& self)
{
Application::reinitialize(self);
// add your own reinitialization code here
}
void defineOptions(OptionSet& options)
{
Application::defineOptions(options);
options.addOption(
Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false)
.callback(OptionCallback<ClassLoaderSample>(this, &ClassLoaderSample::handleHelp)));
}
void handleHelp(const std::string& name, const std::string& value)
{
_helpRequested = true;
displayHelp();
stopOptionsProcessing();
}
void handleConfig(const std::string& name, const std::string& value)
{
loadConfiguration(value);
}
void displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("A PropertySample application that demonstrates how to use Poco::ClassLoader.");
helpFormatter.format(std::cout);
}
int main(const std::vector<std::string>& args)
{
if (!_helpRequested)
{
// ライブラリをロードします。
std::string path = "libTestLibrary";
path.append(SharedLibrary::suffix());
ClassLoader<TestPlugin> cl;
cl.loadLibrary(path);
cl.findClass("PluginA");
cl.findManifest(path);
// ライブラリからインスタンスを作成します。
TestPlugin* pPluginA = cl.classFor("PluginA").create();
std::cout << pPluginA->name() << std::endl;
// 後始末をします。
delete pPluginA;
cl.unloadLibrary(path);
}
return Application::EXIT_OK;
}
private:
bool _helpRequested;
};
POCO_APP_MAIN(ClassLoaderSample) |