您的位置:首页 > 其它

Poco共享库(加载共享库与运行时动态创建实例)

2011-12-22 14:12 573 查看
原文链接http://pocoproject.org/slides/120-SharedLibraries.pdf

1共享库

>当前大部分平台都为运行时加载动态链接库提供了接口,Windows中使用LoadLibrary(),对于大部分的Unix平台使用的是dlopen()。当加载完dll后,要访问dll中的方法必须找到相就方法的地址,找到以后可以用一个函数指针来保存以及调用。

>Poco::SharedLibrary作为一个加载动态链接库的接口,使用时必须加上关文件“Poco/SharedLibrary.h",Poco::SharedLibrary加载动态链接库的方法比较简单,便于寻找地址符号以及缷载。

>Poco::SharedLibrary中常用的方法如下

方法描述
void load(const std::string& path) 根据给定的地址加载动态链接库
void unload()缷载动态链接库
bool hasSysmbol(const std::string& name)根据给定的名字判断库中是否含有相应的方法或符号
void getSysmbol(const std::string& name)根据给定的方法名字获得相应的方法所在的地址
应用实例

// TestLibrary.cpp
#include <iostream>
#if defined(_WIN32)
#define LIBRARY_API __declspec(dllexport)
#else
#define LIBRARY_API
#endif
extern "C" void LIBRARY_API hello();
void hello()
{
std::cout << "Hello, world!" << std::endl;
}
// LibraryLoaderTest.cpp
#include "Poco/SharedLibrary.h"
using Poco::SharedLibrary;
typedef void (*HelloFunc)(); // function pointer type
int main(int argc, char** argv)
{
std::string path("TestLibrary");
path.append(SharedLibrary::suffix()); // adds ".dll" or ".so"
SharedLibrary library(path); // will also load the library
HelloFunc func = (HelloFunc) library.getSymbol("hello");
func();
library.unload();
return 0;
}


2 Class Loader

>Poco::ClassLoader 加载动态链接库的要求比较高,它适用于实现典型的插件体系结构。使用时必须加上头文件“POCO/ClassLoader.h"。要使用Poco::ClassLoader加载的库,要求库中的所有类都必须派生自一个共同的基类。Poco::ClassLoader是一类模版,使用时必须基类来实例化。为什么基类对于Poco::ClassLoader如此重要,这是因为应用程序加载每一个的插件都有相应的访问接口,如何访问这些接口?Poco的设计实现就是通过基来实现的(多态性原理)。

>使用Class Loader加载的动态链接库只能根据基类来导出子类,但这通常不是制约,因为导出的类可以是一个任意对象的类工厂。使用ClassLoader加载的动态链接库也可以导出Manifest,用于描述所有可导出的类的信息。除此以为动态链接库还必须导出一些指定的方法供Class Loader使用,Poco提供一些宏可以自动实现这些方法。

3 Manifest and MetaObject

一个动态链接库的Manifest包含可动态加载的所有类的信息,它管理所有元对象的信息。一个元对象管理所有实例的生命周期,它常用于创建和销毁实例。还有一个特点是它可以导出一个单件(参考设计模式)

4 The MetaObject Class

>MetaObject<Class,Base>是一个类模板,可以实例化它持有的类,MetaObjectObject<Class,Base>派生自AbstractMetaObject<Base>。MetaObject可以用于创建新的实例(除单件模式下)。类似AutoReleasePool,MetaObject也可以自动管理不再需要的对象。MetaObject也可以管理单件对象

>常用的方法

声明描述
const char* name()返回类名
Base* create() const创建新实例
Base& instance()const返回实例
bool canCreate()const判断是否能创建实例
Base* autoDelete(Base* pObject)将pObject所有权交给MetaObject,当pObject销毁时,MetaObject会删除所的对象
bool isAutoDelete(Base* pObject)判断MetaObject是否拥有pObject
void destroy(Base* pObject)如果MetaObject拥有pObject,它会立即删除它
5 The MetaSingleton Class

>它是MetaObject兄弟,用于管理单件,它拥有和MetaObject一样的接口。

6 The Manifest Class

>Poco::Manifest基本是一个元对象的集合,使用时要加头文件“Poco/Manifest.h"。

名称描述
Poco::Manifest::Iterator被用于迭代遍历所有元对象
Manifest::Iterator find(const std::string& className)根据类名来迭代查找元对象
Manifest::Iterator begin() const返回第一个
Manifest::Iterator end()const返回最后一个
7创建一个类库

>一个类库要与class loader一起工作,它必须导出一个manifest,这个类库必须提供一个方法,用于生成一个manifest

bool pocoBuildManifest(ManifestBase* pManifest)
在“Poco/ClassLibrary.h"头文件中提供一些宏用于动态实现这个函数。显然,一个类库可以导出一个初始化和清空的函数。这些宏的使用如下

POCO_BEGIN_MANIFEST(MyBaseClass)
POCO_EXPORT_CLASS(MyFirstClass)
POCO_EXPORT_CLASS(MySecondClass)
POCO_EXPORT_SINGLETON(MySingleton)
POCO_END_MANIFEST


类库能导出一个初始化和清空的方法

void pocoInitializeLibrary()
void pocoUninitializeLibrary()
它们将在class loader中被调用

ClassLoader包含大量的类库及对应的manifest

名称描述
void loadLibrary(const std::string&path)加载库
void loadLibrary(const std::string&path)缷载库
const Meta* findClass(const std::string& className)const根据类名来查找元对象指针
const Meta& ClassFor(const std::string& className)const根据类名来获取元对象的引用
Base* create(const std::string& className)const根据类名来创建实例
Base& instance(const std::string& className)const根据类名来获取单件实例的引用
Iterator begin()const返回第一个
Iterator end()const返回最后一个
实例应用

// AbstractPlugin.h
//
// This is used both by the class library and by the application.
#ifndef AbstractPlugin_INCLUDED
#define AbstractPlugin_INCLUDED
class AbstractPlugin
{
public:
AbstractPlugin();
virtual ~AbstractPlugin();
virtual std::string name() const = 0;
};
#endif // AbstractPlugin.h
// PluginLibrary.cpp
#include "AbstractPlugin.h"
#include "Poco/ClassLibrary.h"
#include <iostream>
class PluginA: public AbstractPlugin
{
public:
std::string name() const
{
return "PluginA";
}
};
class PluginB: public AbstractPlugin
{
public:
std::string name() const
{
return "PluginB";
}
};
POCO_BEGIN_MANIFEST(AbstractPlugin)
POCO_EXPORT_CLASS(PluginA)
POCO_EXPORT_CLASS(PluginB)
POCO_END_MANIFEST
// optional set up and clean up functions
void pocoInitializeLibrary()
{
std::cout << "PluginLibrary initializing" << std::endl;
}
void pocoUninitializeLibrary()
{
std::cout << "PluginLibrary uninitializing" << std::endl;
}


// AbstractPlugin.cpp//
// This is used both by the class library and by the application.
#include "AbstractPlugin.h"
AbstractPlugin::AbstractPlugin(){}
AbstractPlugin::~AbstractPlugin(){}


// main.cpp
#include "Poco/ClassLoader.h"
#include "Poco/Manifest.h"
#include "AbstractPlugin.h"
#include <iostream>
typedef Poco::ClassLoader<AbstractPlugin> PluginLoader;
typedef Poco::Manifest<AbstractPlugin> PluginManifest;
int main(int argc, char** argv)
{
PluginLoader loader;
std::string libName("PluginLibrary");
libName += Poco::SharedLibrary::suffix(); // append .dll or .so
loader.loadLibrary(libName);
PluginLoader::Iterator it(loader.begin());
PluginLoader::Iterator end(loader.end());
for (; it != end; ++it)
{
std::cout << "lib path: " << it->first << std::endl;
PluginManifest::Iterator itMan(it->second->begin());
PluginManifest::Iterator endMan(it->second->end());
for (; itMan != endMan; ++itMan)
std::cout << itMan->name() << std::endl;
}
AbstractPlugin* pPluginA = loader.create("PluginA");
AbstractPlugin* pPluginB = loader.create("PluginB");
std::cout << pPluginA->name() << std::endl;
std::cout << pPluginB->name() << std::endl;
loader.classFor("PluginA").autoDelete(pPluginA);
delete pPluginB;
loader.unloadLibrary(libName);
return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: