一、Plugin SDK模块下沉的两种设计
在大型项目中,框架通常是支持插件加载和插件开发的,这样有助于提升程序的效率和完成更多的第三方的开发需求;因此,在实际场景中,也经常会出现对已有的模块进行下沉,下面给出了两种常用的设计:
1)已有Module基于Core层的封装
这样情况是工程中的Module都基于Core lib 进行封装,封装成PluginSDK 所支持的形式;数据层Module中用的参数,返回值都是Core层所提供的;
2)已有Module基于现有PluginSDK层的封装
这样情况是工程中的Module都基于PluginSDK 进行封装,外部的话可以直接调用;数据层Module中用的参数,返回值都是Plugin SDK层所提供的;
区别:
1)第一种是Module 是直接调用Core 代码,效率高,比较直观好理解;第二种是间接调用,效率会低些,比较抽象点,在某些特殊的场合跨品台性更好,如Web上的一个插件要模仿Win上面来进行实现;
2)第一种负责PluginSDK的人员在封装上可能要多一些;第二种Module在封装的时候已经采用了PluginSDK的数据类型,因此做的封装要少些;
二、基于PluginSDK回调函数设计
基于PluginSDK的回调函数设计和一般的数据类型封装是同样的道理,在我们的PluginSDK都需要对框架的程序数据做一个封装,不同于一般的数据类型或者是指针类型取了一个别名,这里需要对框架中的接口类型进行封装即封装成系列的函数指针,下面给出了简单的示意图:
设计示例代码
//主框架中的接口,框架程序进行管理,在特定的条件下触发
class IReader_UserMessagehandler
{
public:
virtual ~IReader_UserMessagehandler() {}
virtual bool OnUserMessageData(void *pData) { return false; }
};
//PluginSDK的部分
class CFR_ReaderUserMessageHandler : public IReader_UserMessagehandler
{
public:
CFR_ReaderUserMessageHandler(FR_ReaderUserMessageHandlerCallbacks callbacks)
{
memset(&m_callbacks, 0, sizeof(FR_ReaderUserMessageHandlerCallbacksRec));
memcpy(&m_callbacks, callbacks, callbacks->lStructSize);
if (callbacks->lStructSize < sizeof(FR_ReaderUserMessageHandlerCallbacksRec))
{
BYTE * pAttress = (BYTE *)&m_callbacks;
memset(pAttress + callbacks->lStructSize, 0, sizeof(FR_ReaderUserMessageHandlerCallbacksRec) - callbacks->lStructSize);//set new create method to 0.
}
}
virtual ~CFR_ReaderUserMessageHandler() {}
virtual bool OnUserMessageData(void *pData)
{
if (m_callbacks.FROnUserMessageData)
{
return m_callbacks.FROnUserMessageData(m_callbacks.clientData, pData);
}
return false;
}
private:
FR_ReaderUserMessageHandlerCallbacksRec m_callbacks;
};
/
class CFR_ReaderUserMessageHandler_V14 //Internal use
{
public:
static FR_ReaderUserMessageHandler New(FR_ReaderUserMessageHandlerCallbacks callbacks);
static void Destroy(FR_ReaderUserMessageHandler handler);
};
CFR_ReaderUserMessageHandler_V14::New(FR_ReaderUserMessageHandlerCallbacks callbacks)
{
return (FR_ReaderUserMessageHandler)FX_NEW CFR_ReaderUserMessageHandler(callbacks);
}
void CFR_ReaderUserMessageHandler_V14::Destroy(FR_ReaderUserMessageHandler handler)
{
CFR_ReaderUserMessageHandler* pHander = (CFR_ReaderUserMessageHandler*)handler;
delete pHander;
}
/
//框架的实现
class CFR_App_V1
{
public:
static FS_BOOL RegisterUserMessageHanler(FR_ReaderUserMessageHandler handler);
static FS_BOOL UnRegisterUserMessageHanler(FR_ReaderUserMessageHandler handler);
};
FS_BOOL CFR_App_V1::RegisterUserMessageHanler(FR_ReaderUserMessageHandler handler)
{
return g_pReaderAppEx->RegisterUserMessageHanler((CFR_ReaderUserMessageHandler*)handler);
}
FS_BOOL CFR_App_V1::UnRegisterUserMessageHanler(FR_ReaderUserMessageHandler handler)
{
return g_pReaderAppEx->UnRegisterUserMessageHanler((CFR_ReaderUserMessageHandler*)handler);
}
typedef struct _fr_ReaderUserMessageHandler_callbacks_
{
unsigned long lStructSize;
/** The user-supplied data. */
//能够传递一些特殊的信息,如Value或者String,来表明当前注册对象的一些参数、特征等
//或者起到一种标识作用相当于一种唯一ID;也可以理解为一种保留字,暂不使用;
FS_LPVOID clientData;
FS_BOOL(*FROnUserMessageData)(FS_LPVOID clientData, FS_LPVOID pData);
}FR_ReaderUserMessageHandlerCallbacksRec, *FR_ReaderUserMessageHandlerCallbacks;
//*主框架提供了New和Destroy的接口,数据的分配与记录是框架完成的,插件只是申请和释放*
/
//主程序再提供一个注册和撤销的接口,以供不同的插件使用
INTERFACE(FS_BOOL, FRAppRegisterUserMessageHanler, (FR_ReaderUserMessageHandler handler))
INTERFACE(FS_BOOL, FRAppUnRegisterUserMessageHanler, (FR_ReaderUserMessageHandler handler))
注意上面的clientData参数:能够传递一些特殊的信息,如Value或者String,来表明当前注册对象的一些参数、特征等;或者起到一种标识作用相当于一种唯一ID;也可以理解为一种保留字,暂不使用;
调用示例代码
//CDocEventHandler.h
class CDocEventHandler
{
public:
static void RegisterEventHandler(FS_LPVOID clientData);
protected:
static void OnDocPermChange(FS_LPVOID clientData, FR_Document frDoc);
static void OnDocCurrentWndProvideChange(FS_LPVOID clientData, FR_Document frDoc,FS_ByteString fbsWndProvideName);
static void OnDocPageLabelChange(FS_LPVOID clientData, FR_Document frDoc);
protected:
CDocEventHandler() { ; }
~CDocEventHandler() { ; }
static FR_DocEventCallbacksRec m_frCallbacks;
};
//CDocEventHandler.cpp
FR_DocEventCallbacksRec CDocEventHandler::m_frCallbacks = { 0 };
void CDocEventHandler::RegisterEventHandler(FS_LPVOID clientData)
{
m_frCallbacks.lStructSize = sizeof(FR_DocEventCallbacksRec);
m_frCallbacks.clientData = clientData;
m_frCallbacks.FRDocOnPermissionChange = OnDocPermChange;
m_frCallbacks.FROnDocCurrentWndProvideChange = OnDocCurrentWndProvideChange;
m_frCallbacks.FROnDocPageLabelChange = OnDocPageLabelChange;
FRAppRegisterDocHandlerOfPDDoc(&m_frCallbacks);
}
//GlobalHandler.cpp实际的调用
void CGlobalHandler::Initialize(HINSTANCE dllInstance)
{
assert(dllInstance);
//.....
CDocEventHandler::RegisterEventHandler(nullptr);
//.....
}