之所以命名为浅谈,是因为对作者的构思还不是很清楚,有许多的内容理解不透彻,所以先简单的谈一下
1 x3架构中关于各个ID的理解
X3CLSID
提起这个,就不得不说一下,宏的应用
#define X3CLSID_DEFINE(clsid, str) \
namespace x3 { static const X3CLSID clsid(str); } \
typedef int dumy_ ## clsid
其应用场景如下:X3CLSID_DEFINE(CLSID_StringTable, "b8c36b29-59c3-4db2-be43-fd4982e6e71d");
是在每个模块定义的开头,调用, Cx_Interface<Ix_StringTable> pIFTable(x3::CLSID_StringTable);将本地
在宏调用中,第一个传入参数定义了全局变量,第二个参数定义了模块的CLSID,引用调用的话,就可以用第一个参量进行
引用调用,不得不说,这个宏还是挺通用的
X3IID
#define X3DEFINE_IID(_Interface) \
virtual ~_Interface() {} \
static X3IID GetIID() { static X3IID id = x3::hashkey(#_Interface); return id; }
其应用场景:X3DEFINE_IID(Ix_StringTable)
在每个模块内部,定义了一个静态常量,以便之后引用,但是应用上倒没有学会怎么用了
X3CLASSENTRY
这个结构是创建模块以及管理模块单一对象,其中存储了关于模块的引用信息以及属性
//! class factory function.
typedef Ix_Object* (*PFNXObjectCreator)(X3IID, HMODULE);
//! object count of a class.
typedef long (*PFNXGetObjectCount)();
//! object (used by other modules) count of a class.
typedef long (*PFNXRefCountByOthers)();
定义了模块的创建函数,此函数通过模块内部的X3IID,找到模块名和句柄,并创建或者说是加载
返回了本模块的引用计数
返回了本模块被其他模块引用的计数
class X3CLASSENTRY
{
public:
BYTE type; //!< see MIN_SINGLETON_TYPE and XModuleMacro.h
const char* className; //!< implement class name
X3CLSID clsid; //!< class id
PFNXObjectCreator pfnObjectCreator; //!< class factory function
PFNXGetObjectCount pfnGetObjectCount; //!< object count of this class
PFNXRefCountByOthers pfnRefCountByOthers; //!< count of objects used by other modules
//! Used by XDEFINE_CLASSMAP_ENTRY, XDEFINE_CLASSMAP_ENTRY_Singleton
X3CLASSENTRY(BYTE _type,
const char* _className,
const X3CLSID& _clsid,
PFNXObjectCreator _pfnObjectCreator,
PFNXGetObjectCount _pfnGetObjectCount = NULL,
PFNXRefCountByOthers _pfnRefCountByOthers = NULL)
: type(_type), className(_className), clsid(_clsid)
, pfnObjectCreator(_pfnObjectCreator)
, pfnGetObjectCount(_pfnGetObjectCount)
, pfnRefCountByOthers(_pfnRefCountByOthers)
{
}
//! Used by XEND_DEFINE_MODULE
X3CLASSENTRY()
: type(0), className(""), clsid("")
, pfnObjectCreator(NULL), pfnGetObjectCount(NULL)
, pfnRefCountByOthers(NULL)
{
}
//! class factory registries. filled by XBEGIN_DEFINE_MODULE.
static const X3CLASSENTRY s_classes[];
};
//! Begin group of class factory registry.
/*!
\ingroup _GROUP_PLUGIN_CORE_
\see XEND_DEFINE_MODULE
\see XEND_DEFINE_MODULE_DLL, XEND_DEFINE_MODULE_MFCEXTDLL
*/
#define XBEGIN_DEFINE_MODULE() \
const X3CLASSENTRY X3CLASSENTRY::s_classes[] = {
//! Register a regular class.
/*!
\ingroup _GROUP_PLUGIN_CORE_
\param clsid class unique id, X3CLSID constant.
\param cls implement class
*/
#define XDEFINE_CLASSMAP_ENTRY(clsid, cls) \
X3CLASSENTRY(1, "Cx_Object<" #cls ">", clsid, \
reinterpret_cast<PFNXObjectCreator>(&Cx_Object<cls>::CreateObject), \
reinterpret_cast<PFNXGetObjectCount>(&Cx_Object<cls>::GetObjectCount), \
reinterpret_cast<PFNXRefCountByOthers>(&Cx_Object<cls>::GetRefCountByOthers)),
//! Register a single instance class.
/*!
\ingroup _GROUP_PLUGIN_CORE_
\param clsid class unique id, X3CLSID constant.
\param cls implement class
*/
#define XDEFINE_CLASSMAP_ENTRY_Singleton(clsid, cls) \
X3CLASSENTRY(MIN_SINGLETON_TYPE, \
"Cx_SingletonObject<" #cls ">", clsid, \
reinterpret_cast<PFNXObjectCreator>(&Cx_SingletonObject<cls>::CreateObject), \
reinterpret_cast<PFNXGetObjectCount>(&Cx_SingletonObject<cls>::GetObjectCount), \
reinterpret_cast<PFNXRefCountByOthers>(&Cx_SingletonObject<cls>::GetRefCountByOthers)),
//! End group of class factory registry.
/*!
\ingroup _GROUP_PLUGIN_CORE_
\see XEND_DEFINE_MODULE_DLL, XEND_DEFINE_MODULE_MFCEXTDLL
*/
#define XEND_DEFINE_MODULE() \
X3CLASSENTRY() \
};
XDEFINE_CLASSMAP_ENTRY_Singleton(x3::CLSID_StringTable, Cx_StringTable)
这个结构的应用一般在模块定义接口实现文件中,此宏通过Cx_Object的模版类,后延到ClsType以及模块定义类的宏定义
的函数中。其中Creator函数就是询问子类实现中,是否由此接口模块,并实现了此接口。另外两个接口分别返回的是程序中
有多少这个接口对象以及被其他引用的计数是多少。
XDEFINE_CLASSMAP_ENTRY_Singleton(x3::CLSID_ConfigDBFactory, Cx_ConfigFactory)
或者定义的静态对象实例,需要用到Cx_ModuleItem对此实例进行管理。
除了在模块实现文件Module.cpp中定义了全局的一些结构外,还在XClassMacro中定义了每个实现的接口函数
//! Begin definition group of how many interfaces supported by the class.
/*!
\ingroup _GROUP_PLUGIN_CORE_
\param cls class name.
\see X3END_CLASS_DECLARE, X3DEFINE_INTERFACE_ENTRY, X3USE_INTERFACE_ENTRY
\code
class Cx_Example : public Cx_Base, public Ix_Example
{
X3BEGIN_CLASS_DECLARE(Cx_Example)
X3DEFINE_INTERFACE_ENTRY(Ix_Example)
X3USE_INTERFACE_ENTRY(Cx_Base)
X3END_CLASS_DECLARE()
protected:
Cx_Example();
virtual ~Cx_Example();
private:
virtual void foo();
};
\endcode
*/
#define X3BEGIN_CLASS_DECLARE(cls) \
public: \
const char* DoGetClassName() const { return #cls; } \
static bool DoQueryInterface(cls* self, X3IID iid, Ix_Object** ppv, HMODULE fromdll) \
{
//! Indicate a interface is supported by the class.
/*!
\ingroup _GROUP_PLUGIN_CORE_
\param _Interface interface name.
\see X3BEGIN_CLASS_DECLARE, X3USE_INTERFACE_ENTRY
*/
#define X3DEFINE_INTERFACE_ENTRY(_Interface) \
if (iid == _Interface::GetIID()) \
{ \
*ppv = static_cast<Ix_Object*>(static_cast<_Interface*>(self)); \
(*ppv)->InterfaceAddRef(fromdll); \
return true; \
}
//! Indicate this class is derived from a implement class.
/*! All interfaces of the base class are supported by this class.
\ingroup _GROUP_PLUGIN_CORE_
\param _BaseClass base class that has the group declared using X3BEGIN_CLASS_DECLARE.
\see X3BEGIN_CLASS_DECLARE, X3DEFINE_INTERFACE_ENTRY
*/
#define X3USE_INTERFACE_ENTRY(_BaseClass) \
if (_BaseClass::DoQueryInterface(self, iid, ppv, fromdll)) \
{ \
return true; \
}
//! End group of class definition.
/*!
\see X3BEGIN_CLASS_DECLARE, X3DEFINE_INTERFACE_ENTRY
*/
#define X3END_CLASS_DECLARE() \
return false; \
}
X3BEGIN_CLASS_DECLARE(Cx_StringTable)
X3DEFINE_INTERFACE_ENTRY(Ix_StringTable)
X3END_CLASS_DECLARE()
这些宏用于每个实现接口的文件中,用于定义之前宏用到的一些查询函数,以及父类接口的查询。
Cx_ObjectFactory
这个是管理各个子模块的管理类了,相当于企业ceo,实现了两个接口以及模块加载一系列函数。
其接口包括了 virtual bool IsCreatorRegister(const X3CLSID& clsid);
virtual int CreateObject(const X3CLSID& clsid, X3IID iid, Ix_Object** ppv, HMODULE fromdll);
其余均是模块内部定义的自使用函数。
其结构包括了 vector<X3CLSID> CLSIDS;
std::pair<X3ClassEntry,long> MAPITEM;
hash_map<std::string,MAPITEM> CLSMAP;
每个模块中可能含有若干个接口,所以定义了模块结构
struct MODULE //!< plugin module info
{
HMODULE hdll; //!< DLL handle of the plugin
Ix_Module* module; //!< plugin module object
CLSIDS clsids; //!< all classes of the plugin
bool owned; //!< the DLL is loaded by this class or not
bool inited; //!< InitializePlugins() has been called or not
wchar_t filename[MAX_PATH]; //!< plugin filename
MODULE() : hdll(NULL), module(NULL), owned(false), inited(false) {}
};
然后本对象所含的主要对象已经昭然若揭了
std::vector<MODULE *> m_modules;
CLSMAP m_clsmap;
long m_unloading;
long m_loading;
应用的主要目的就是管理这些模块,外部模块,首先将之加载进去LoadLibrary,定位GetProcAddress其x3InitializePlugin,如果可以
获得本模块的函数导出,那么就说明此模块已经被加载,此时直接卸载掉,否则就获取DllGetClassObject进行加载