7. クラスローディング

今回は、POCOでのクラスローディングの実装例を詳解します。
まず、参考情報のポインタを示します。
http://pocoproject.org/slides/120-SharedLibraries.pdf

さて、このクラスローディングはPOCO独自の機能で、シェアドライブラリからプログラム実行時にクラスを動的生成することができます。
シェアドライブラリを追加・変更することで、プログラムの振る舞いを変更できますので、主な用途としてはプラグインが挙げられます。
クラスローディングのサンプルコードは、シェアドライブラリのコードとクラスローディングするコードの2つに分かれます。

シェアドライブラリ;TestPlugin.h

C++
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

C++
1
2
3
4
5
6
7
8
9
#include "TestPlugin.h"
TestPlugin::TestPlugin()
{
}
TestPlugin::~TestPlugin()
{
}

シェアドライブラリ;TestLibrary.cpp

C++
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

C++
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)

Comments are closed.