ClassLoader手册.
------------------
目标DLLs应该导出一个名叫GetClassObject的函数,使用C语言链接。
如下:
在头文件中
extern "C" {
IClassFactory* GetClassObject();
}
在源代码文件中:
extern "C" {
IClassFactory* GetClassObject()
{
return new ExampleFactory();
}
}
工厂应该从IClassFactory这个抽象类继承,必须实现来自IUnknown接口QueryInterface方法,AddRef和Release方法已经默认提供了实现。
CLSID类提供了用于访问标识对像的GUIDs。这个类可以通过C或C++字符串进行初始化。这个字符串可以是任何形式的,但基于系统正常运行的考虑,它们必须是唯一的。classloader库使用"ClassLoader::ExampleObject"格式的字符串,这里ClassLoader看起来就像ExampleObject接口的命名空间似的。你还可以同时提供附加的版本信息,这样做不是必须的。这样做建议的语法是:"ClassLoader::ExampleObject@1.0"
每一个从IUnknown继承进而实现了QueryInterface接口的类都应该定义它自己的CLSID,如果它是有用这种方式的话。
ConfigureClassLoader是非常有用的类提供者。它雇用ClassLoader帮它完成这项工作,但是也从IDynamicClassLoader继承其接口。它需要xml文件的路径作为其构造函数的参数。这是用来将CLSIDs映射到sonames(用于dlopen的共享库名字)
使用用库来加载对象:
你的程序需要为你想加载的外部库的每种类型的对象定义"一个"抽象基类。这些库需要和你的源代码一起编译,并且安装在一个可供动态加载器访问的目录:/usr/lib,/usr/local/lib或者在/etc/ld.so.conf中的文件夹列表中的任意一个,或者在LD_LIBRARY_PATH环境变量中的文件夹中(如果你这样用的话,你必须在程序每一次运行之前都要设置它)
(什么情况下你可以用类加载器)
如果你已经用CLSID对要加载的动态库名作了硬编码了,或者你已经有单独的方法去发现他们(CLSID和soname的对应关系),你就可以不用创建你自己的类加载器了。这时可以直接使用ClassLoader对象:
MyClass *obj;
ClassLoader *cl = new ClassLoader();
IClassFactory *cf = cl->GetClassObject( (string)soname );
int result = cf->CreateInstance( (CLSID)clsid, &obj );
.....
obj->Release();
delete cl;
delete cf;
然而使用类加载器的最佳方法是通过ConfigureClassLoader,像这样:
MyClass *obj;
ConfiguredClassLoader *ccl = new ConfiguredClassLoader( (string)xml_file_path );
/* this causes the xml file to be parsed
* and the mapping from CLSIDs to sonames to be created
*/
IClassFactory *cf = ccl->GetClassObject( (CLSID)clsid, &obj );
int result = cf->CreateInstance( (CLSID)clsid, &obj );
etc.
如果你想使用曾经是唯一的方式创建一个单独的对象。你可以通过ClassLoader和ConfiguredClassLoader提供的快捷方式来实现:
ClassLoader *cl = new ClassLoader();
int result = cl->CreateInstance( soname, clsid, (void**)&obj );
// check result
// use `obj'
类似地:
ConfiguredClassLoader *ccl = new ConfiguredClassLoader( xml_file_path );
int result = ccl->CreateInstance( clsid, (void**)&obj );
请注意,这样做时其实是隐式地创建一个工厂对象,接着创建了你需要的对象,然后销毁工厂对象。不要使用这种方法创建大量的类似对象--这是很消耗cpu时间的。建议的用法是,使用上面的方法创建一次工厂对象,然后使用它创建尽可能多的对象。
查看docs/classloader.dtd和docs/sample.xml学习如何创建一个有效的XML配置文件;同时看一下示例文件夹下的示例程序和库。它们展示了本文档所描述的技术。
bugs和设计缺陷总是在所难免,但请反馈给我,这样我可以进一步的完善这段代码。
Chris Dawes, cmsd2@cam.ac.uk