博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SOUI新组件SIpcObject介绍
阅读量:6655 次
发布时间:2019-06-25

本文共 18246 字,大约阅读时间需要 60 分钟。

SIpcObject是一个基于Windows消息及共享内存的一个IPC(跨进程函数调用)的组件。

GITHUB上有很多IPC模块,我这里又造了一个轮子,不一定比现有的IPC更好,不过我觉得已经足够简单了。

老规矩,先看一下IPC模块的路径: 

 

再看一下IPC模块的接口:

1 #pragma once  2   3 #include 
4 5 #define UM_CALL_FUN (WM_USER+1000) 6 7 namespace SOUI 8 { 9 enum { 10 FUN_ID_CONNECT = 100, 11 FUN_ID_DISCONNECT, 12 FUN_ID_START, 13 }; 14 15 struct IShareBuffer { 16 virtual void StartRead() = 0; 17 virtual void StartWrite() = 0; 18 virtual int Write(const void * data, UINT nLen) = 0; 19 virtual int Read(void * buf, UINT nLen) = 0; 20 }; 21 22 23 class SParamStream 24 { 25 public: 26 SParamStream(IShareBuffer *pBuf, bool bOutStream) :m_pBuffer(pBuf) 27 { 28 m_pBuffer->StartRead(); 29 if (bOutStream) m_pBuffer->StartWrite(); 30 } 31 32 IShareBuffer * GetBuffer() { 33 return m_pBuffer; 34 } 35 36 template
37 SParamStream & operator<<(const T & data) 38 { 39 Write((const void*)&data, sizeof(data)); 40 return *this; 41 } 42 43 44 template
45 SParamStream & operator >> (T &data) 46 { 47 Read((void*)&data, sizeof(data)); 48 return *this; 49 } 50 51 public: 52 int Write(const void * data, int nLen) 53 { 54 return m_pBuffer->Write(data, nLen); 55 } 56 int Read(void * buf, int nLen) 57 { 58 return m_pBuffer->Read(buf, nLen); 59 } 60 61 protected: 62 IShareBuffer * m_pBuffer; 63 }; 64 65 struct IFunParams 66 { 67 virtual UINT GetID() = 0; 68 virtual void ToStream4Input(SParamStream & ps) = 0; 69 virtual void ToStream4Output(SParamStream & ps) = 0; 70 virtual void FromStream4Input(SParamStream & ps) = 0; 71 virtual void FromStream4Output(SParamStream & ps) = 0; 72 }; 73 74 struct IIpcConnection; 75 struct IIpcHandle : IObjRef 76 { 77 virtual void SetIpcConnection(IIpcConnection *pConn) = 0; 78 79 virtual IIpcConnection * GetIpcConnection() const = 0; 80 81 virtual LRESULT OnMessage(ULONG_PTR idLocal, UINT uMsg, WPARAM wp, LPARAM lp, BOOL &bHandled) = 0; 82 83 virtual HRESULT ConnectTo(ULONG_PTR idLocal, ULONG_PTR idRemote) = 0; 84 85 virtual HRESULT Disconnect() = 0; 86 87 virtual bool CallFun(IFunParams * pParam) const = 0; 88 89 virtual ULONG_PTR GetLocalId() const = 0; 90 91 virtual ULONG_PTR GetRemoteId() const = 0; 92 93 virtual IShareBuffer * GetSendBuffer() = 0; 94 95 virtual IShareBuffer * GetRecvBuffer() = 0; 96 97 virtual BOOL InitShareBuf(ULONG_PTR idLocal, ULONG_PTR idRemote, UINT nBufSize, void* pSa) = 0; 98 }; 99 100 struct IIpcConnection : IObjRef101 {102 virtual IIpcHandle * GetIpcHandle() = 0;103 virtual bool HandleFun(UINT uFunID, SParamStream & ps) = 0;104 virtual void BuildShareBufferName(ULONG_PTR idLocal, ULONG_PTR idRemote, TCHAR szBuf[MAX_PATH]) const = 0;105 };106 107 struct IIpcSvrCallback 108 {109 virtual void OnNewConnection(IIpcHandle * pIpcHandle, IIpcConnection ** ppConn) = 0;110 virtual int GetBufSize() const = 0;111 virtual void * GetSecurityAttr() const = 0;112 virtual void ReleaseSecurityAttr(void* psa) const = 0;113 };114 115 struct IIpcServer : IObjRef116 {117 virtual HRESULT Init(ULONG_PTR idSvr, IIpcSvrCallback * pCallback) =0;118 virtual void CheckConnectivity() =0;119 virtual LRESULT OnMessage(ULONG_PTR idLocal, UINT uMsg, WPARAM wp, LPARAM lp,BOOL &bHandled) =0;120 };121 122 struct IIpcFactory : IObjRef123 {124 virtual HRESULT CreateIpcServer(IIpcServer ** ppServer) =0;125 virtual HRESULT CreateIpcHandle(IIpcHandle ** ppHandle) =0;126 };127 128 129 }

和所有SOUI的组件一样,可以通过SOUI::IPC::SCreateInstance来创建IPC组件的IIpcFactory接口。

有了这个接口就可以用来创建IIpcServer和IIpcHandle这两个对象了。

IIpcServer是在IPC的服务端运行的接口,IIpcHandle是用来在服务端和客户端通讯的接口,在服务端,IIpcHandle由IIpcServer在客户端发起连接请求时自动创建,在客户端则直接使用IIpcFactory创建。

IIpcHandle是由SIpcObject实现的,在应用层中只需要直接使用。

应用层为了实现客户端与服务器的通讯还需要定义好协议。

SIpcObject的协议就是一个继承自IFunParam接口的定义的调用方法ID及方法参数。

下面看一下启程输入法使用IpcObject的协议定义。

1 #pragma once  2 #include 
3 #include
4 #include "sinstar-i.h" 5 #include "TextService-i.h" 6 #include
7 #include
8 9 #define SINSTAR3_SERVER_HWND _T("sinstar3_server_wnd_{85B55CBC-7D48-4860-BA88-0BE4B073A94F}") 10 #define SINSTAR3_SHARE_BUF_NAME_FMT _T("sistart3_share_buffer_8085395F-E2FA-4F96-8BD0-FE5D7412CD22_%08x_2_%08x") 11 12 13 // 14 namespace SOUI{ 15 16 template<> 17 inline SParamStream & SParamStream::operator<<(const std::string & str) 18 { 19 int nSize = (int)str.size(); 20 GetBuffer()->Write((const BYTE*)&nSize, sizeof(int)); 21 GetBuffer()->Write((const BYTE*)str.c_str(), nSize); 22 return *this; 23 } 24 template<> 25 inline SParamStream & SParamStream::operator >> (std::string & str) 26 { 27 int nSize = 0; 28 GetBuffer()->Read((BYTE*)&nSize, sizeof(int)); 29 char *pBuf = new char[nSize]; 30 GetBuffer()->Read((BYTE*)pBuf, nSize); 31 str = std::string(pBuf, nSize); 32 delete[]pBuf; 33 return *this; 34 } 35 36 37 template<> 38 inline SParamStream & SParamStream::operator<<(const std::wstring & str) 39 { 40 int nSize = (int)str.size(); 41 GetBuffer()->Write((const BYTE*)&nSize, sizeof(int)); 42 GetBuffer()->Write((const BYTE*)str.c_str(), nSize*sizeof(wchar_t)); 43 return *this; 44 } 45 template<> 46 inline SParamStream & SParamStream::operator >> (std::wstring & str) 47 { 48 int nSize = 0; 49 GetBuffer()->Read((BYTE*)&nSize, sizeof(int)); 50 wchar_t *pBuf = new wchar_t[nSize]; 51 GetBuffer()->Read((BYTE*)pBuf, nSize*sizeof(wchar_t)); 52 str = std::wstring(pBuf, nSize); 53 delete[]pBuf; 54 return *this; 55 } 56 57 // 58 template<> 59 inline SParamStream & SParamStream::operator<<(const POINT & pt) 60 { 61 GetBuffer()->Write((const BYTE*)&pt.x, sizeof(int)); 62 GetBuffer()->Write((const BYTE*)&pt.y, sizeof(int)); 63 return *this; 64 } 65 template<> 66 inline SParamStream & SParamStream::operator >> (POINT & pt) 67 { 68 int tmp = 0; 69 GetBuffer()->Read((BYTE*)&tmp, sizeof(int)); 70 pt.x = tmp; 71 GetBuffer()->Read((BYTE*)&tmp, sizeof(int)); 72 pt.y = tmp; 73 return *this; 74 } 75 76 } 77 78 struct FunParams_Base : SOUI::IFunParams 79 { 80 virtual void ToStream4Input(SOUI::SParamStream & ps) {} 81 virtual void ToStream4Output(SOUI::SParamStream & ps) {} 82 virtual void FromStream4Input(SOUI::SParamStream & ps) {} 83 virtual void FromStream4Output(SOUI::SParamStream & ps) {} 84 }; 85 86 87 enum { 88 ISinstar_Create = SOUI::FUN_ID_START, 89 ISinstar_Destroy, 90 ISinstar_OnImeSelect, 91 ISinstar_OnCompositionStarted, 92 ISinstar_OnCompositionChanged, 93 ISinstar_OnCompositionTerminated, 94 ISinstar_OnSetCaretPosition, 95 ISinstar_OnSetFocusSegmentPosition, 96 ISinstar_ProcessKeyStoke, 97 ISinstar_TranslateKey, 98 ISinstar_OnSetFocus, 99 ISinstar_GetCompositionSegments,100 ISinstar_GetCompositionSegmentEnd,101 ISinstar_GetCompositionSegmentAttr,102 ISinstar_OnOpenStatusChanged,103 ISinstar_OnConversionModeChanged,104 ISinstar_ShowHelp,105 ISinstar_GetDefInputMode,106 107 ITextService_InputStringW = ISinstar_GetDefInputMode + 100,108 ITextService_IsCompositing,109 ITextService_StartComposition,110 ITextService_ReplaceSelCompositionW,111 ITextService_UpdateResultAndCompositionStringW,112 ITextService_EndComposition,113 ITextService_GetImeContext,114 ITextService_ReleaseImeContext,115 ITextService_SetConversionMode,116 ITextService_GetConversionMode,117 ITextService_SetOpenStatus,118 ITextService_GetOpenStatus,119 ITextService_GetActiveWnd,120 };121 122 123 struct Param_Create : FunParams_Base124 {125 bool bDpiAware;126 std::string strHostPath;127 DWORD dwVer;128 FUNID(ISinstar_Create)129 PARAMS3(Input, bDpiAware,strHostPath,dwVer)130 };131 132 struct Param_Destroy : FunParams_Base133 {134 FUNID(ISinstar_Destroy)135 };136 137 struct Param_OnImeSelect : FunParams_Base138 {139 BOOL bSelect;140 FUNID(ISinstar_OnImeSelect)141 PARAMS1(Input, bSelect)142 };143 144 struct Param_OnCompositionStarted : FunParams_Base145 {146 FUNID(ISinstar_OnCompositionStarted)147 };148 149 150 struct Param_OnCompositionTerminated : FunParams_Base151 {152 bool bClearCtx;153 FUNID(ISinstar_OnCompositionTerminated)154 PARAMS1(Input, bClearCtx)155 };156 157 struct Param_OnCompositionChanged : FunParams_Base158 {159 FUNID(ISinstar_OnCompositionChanged)160 };161 162 struct Param_OnSetCaretPosition : FunParams_Base163 {164 POINT pt;165 int nHei;166 FUNID(ISinstar_OnSetCaretPosition)167 PARAMS2(Input, pt,nHei)168 };169 170 struct Param_OnSetFocusSegmentPosition : FunParams_Base171 {172 POINT pt; int nHei;173 FUNID(ISinstar_OnSetFocusSegmentPosition)174 PARAMS2(Input, pt, nHei)175 };176 177 struct Param_ProcessKeyStoke : FunParams_Base {178 UINT64 lpImeContext; UINT vkCode; DWORD lParam; BOOL bKeyDown; 179 BYTE byKeyState[256];180 BOOL bEaten;181 FUNID(ISinstar_ProcessKeyStoke)182 PARAMS5(Input, lpImeContext, vkCode, lParam, bKeyDown, byKeyState)183 PARAMS1(Output,bEaten)184 };185 186 struct Param_TranslateKey : FunParams_Base187 {188 UINT64 lpImeContext; UINT vkCode; UINT uScanCode; BOOL bKeyDown; 189 BYTE byKeyState[256];190 BOOL bEaten;191 FUNID(ISinstar_TranslateKey)192 PARAMS5(Input, lpImeContext, vkCode, uScanCode, bKeyDown, byKeyState)193 PARAMS1(Output, bEaten)194 };195 196 struct Param_OnSetFocus : FunParams_Base197 {198 BOOL bFocus;199 FUNID(ISinstar_OnSetFocus)200 PARAMS1(Input, bFocus)201 };202 203 struct Param_GetCompositionSegments : FunParams_Base204 {205 int nSegs;206 FUNID(ISinstar_GetCompositionSegments)207 PARAMS1(Output, nSegs)208 };209 210 struct Param_GetCompositionSegmentEnd : FunParams_Base211 {212 int iSeg;213 int iEnd;214 FUNID(ISinstar_GetCompositionSegmentEnd)215 PARAMS1(Input,iSeg)216 PARAMS1(Output,iEnd)217 };218 219 struct Param_GetCompositionSegmentAttr : FunParams_Base220 {221 int iSeg;222 int nAttr;223 FUNID(ISinstar_GetCompositionSegmentAttr)224 PARAMS1(Input, iSeg)225 PARAMS1(Output, nAttr)226 };227 228 struct Param_OnOpenStatusChanged : FunParams_Base229 {230 BOOL bOpen;231 FUNID(ISinstar_OnOpenStatusChanged)232 PARAMS1(Input, bOpen)233 };234 235 struct Param_OnConversionModeChanged : FunParams_Base236 {237 EInputMethod uMode;238 FUNID(ISinstar_OnConversionModeChanged)239 PARAMS1(Input, uMode)240 };241 242 struct Param_ShowHelp : FunParams_Base243 {244 FUNID(ISinstar_ShowHelp)245 };246 247 struct Param_GetDefInputMode : FunParams_Base248 {249 EInputMethod uMode;250 FUNID(ISinstar_GetDefInputMode)251 PARAMS1(Output,uMode)252 };253 254 255 ////256 struct Param_InputStringW : FunParams_Base257 {258 std::wstring buf;259 BOOL bRet;260 FUNID(ITextService_InputStringW)261 PARAMS1(Input,buf)262 PARAMS1(Output,bRet)263 };264 265 struct Param_IsCompositing : FunParams_Base266 {267 BOOL bRet;268 FUNID(ITextService_IsCompositing)269 PARAMS1(Output,bRet)270 };271 272 struct Param_StartComposition : FunParams_Base273 {274 UINT64 lpImeContext;275 FUNID(ITextService_StartComposition)276 PARAMS1(Input,lpImeContext)277 };278 279 struct Param_ReplaceSelCompositionW : FunParams_Base280 {281 UINT64 lpImeContext; int nLeft; int nRight; std::wstring buf;282 FUNID(ITextService_ReplaceSelCompositionW)283 PARAMS4(Input,lpImeContext,nLeft,nRight,buf)284 };285 286 struct Param_UpdateResultAndCompositionStringW : FunParams_Base287 {288 UINT64 lpImeContext; std::wstring resultStr; std::wstring compStr;289 FUNID(ITextService_UpdateResultAndCompositionStringW)290 PARAMS3(Input, lpImeContext, resultStr, compStr)291 };292 293 struct Param_EndComposition : FunParams_Base294 {295 UINT64 lpImeContext;296 FUNID(ITextService_EndComposition)297 PARAMS1(Input,lpImeContext)298 };299 300 struct Param_GetImeContext : FunParams_Base301 {302 UINT64 lpImeContext;303 FUNID(ITextService_GetImeContext)304 PARAMS1(Output,lpImeContext)305 };306 307 struct Param_ReleaseImeContext : FunParams_Base308 {309 UINT64 lpImeContext;310 BOOL bRet;311 FUNID(ITextService_ReleaseImeContext)312 PARAMS1(Input, lpImeContext)313 PARAMS1(Output,bRet)314 };315 316 struct Param_SetConversionMode : FunParams_Base317 {318 EInputMethod mode;319 FUNID(ITextService_SetConversionMode)320 PARAMS1(Input,mode)321 };322 323 struct Param_GetConversionMode : FunParams_Base324 {325 EInputMethod mode;326 FUNID(ITextService_GetConversionMode)327 PARAMS1(Output, mode)328 };329 330 struct Param_SetOpenStatus : FunParams_Base331 {332 UINT64 lpImeContext;333 BOOL bOpen;334 BOOL bRet;335 FUNID(ITextService_SetOpenStatus)336 PARAMS2(Input,lpImeContext,bOpen)337 PARAMS1(Output,bRet)338 };339 340 struct Param_GetOpenStatus : FunParams_Base341 {342 UINT64 lpImeContext;343 BOOL bOpen;344 FUNID(ITextService_GetOpenStatus)345 PARAMS1(Input, lpImeContext)346 PARAMS1(Output, bOpen)347 };348 349 struct Param_GetActiveWnd : FunParams_Base350 {351 DWORD hActive;352 FUNID(ITextService_GetActiveWnd)353 PARAMS1(Output, hActive)354 }
首先我们通过一组枚举值定义所有调用的函数ID。

然后实现一个继承自IFunParams的对象FunParams_Base,以实现接口中的缺省方法。

然后从FunParams_Base继承出每一个IPC调用需要的参数。

我们以256行的Param_InputStringW为例来说明如何定义方法参数。

struct Param_InputStringW : FunParams_Base{    std::wstring buf;    BOOL bRet;    FUNID(ITextService_InputStringW)        PARAMS1(Input,buf)        PARAMS1(Output,bRet)};

这个IPC调用输入是一个wstring字符串,输出是一个BOOL类型返回值。

首先在对象中定义这两个成员变量。

定义好后通过宏FUNID来指定这个方法的函数调用ID。

再通过宏PARAM1(Input,buf)来指定这个方法的输入参数buf, 注意宏的第一个参数"input"。

第三步通过宏PARAM1(output,bRet)来定义这个方法的输出变量为bRet. PARAMX目前实现的X范围为1-5, 分别对应1-5个参数,如果在一次调用中有更多参数,可以参考PARAMX的实现多写几个宏就好了。

实际上这些宏就是为了组合IFunParams的几个虚方法。

这个对象在进行IPC调用的时候,先在请求端借助SParamStream对象序列化到共享内存中,SParamStream重载了输入"<<"及输出">>"操作符,默认操作是直接拷贝变量内存,这对于基本变量类型是适用的,但是对于string,wstring等对象就不适用了,对于那些不能通过简单的内存拷贝来传递的对象,我们需要像协议开头那样为这些类型的序列化做模板特化。对于比如POINT这样的对象也是可以直接通过内存拷贝就可以实现序列化的,因此这里对POINT的特化其实是多余的(最新的代码已经删除)。

协议定义好后,我们来看看如何进行IPC调用及响应IPC调用。

1 class CClientConnection : public SOUI::TObjRefImpl
2 { 3 public: 4 CClientConnection(ITextService * pTxtService); 5 6 public: 7 // 通过 IIpcConnection 继承 8 virtual SOUI::IIpcHandle * GetIpcHandle() override; 9 virtual void BuildShareBufferName(ULONG_PTR idLocal, ULONG_PTR idRemote, TCHAR szName[MAX_PATH]) const override;10 bool CallFun(SOUI::IFunParams *params) const;11 protected:12 void OnInputStringW( Param_InputStringW &param);13 void OnIsCompositing( Param_IsCompositing &param);14 void OnStartComposition( Param_StartComposition &param);15 void OnReplaceSelCompositionW( Param_ReplaceSelCompositionW &param);16 void OnUpdateResultAndCompositionStringW( Param_UpdateResultAndCompositionStringW &param);17 void OnEndComposition( Param_EndComposition &param);18 void OnGetImeContext( Param_GetImeContext &param);19 void OnReleaseImeContext( Param_ReleaseImeContext &param);20 void OnSetConversionMode( Param_SetConversionMode &param);21 void OnGetConversionMode( Param_GetConversionMode &param);22 void OnSetOpenStatus( Param_SetOpenStatus &param);23 void OnGetOpenStatus( Param_GetOpenStatus &param);24 void OnGetActiveWnd( Param_GetActiveWnd &param);25 26 FUN_BEGIN27 FUN_HANDLER(Param_InputStringW, OnInputStringW)28 FUN_HANDLER(Param_IsCompositing, OnIsCompositing)29 FUN_HANDLER(Param_StartComposition, OnStartComposition)30 FUN_HANDLER(Param_ReplaceSelCompositionW, OnReplaceSelCompositionW)31 FUN_HANDLER(Param_UpdateResultAndCompositionStringW, OnUpdateResultAndCompositionStringW)32 FUN_HANDLER(Param_EndComposition, OnEndComposition)33 FUN_HANDLER(Param_GetImeContext, OnGetImeContext)34 FUN_HANDLER(Param_ReleaseImeContext, OnReleaseImeContext)35 FUN_HANDLER(Param_SetConversionMode, OnSetConversionMode)36 FUN_HANDLER(Param_GetConversionMode, OnGetConversionMode)37 FUN_HANDLER(Param_SetOpenStatus, OnSetOpenStatus)38 FUN_HANDLER(Param_GetOpenStatus, OnGetOpenStatus)39 FUN_HANDLER(Param_GetActiveWnd, OnGetActiveWnd)40 FUN_END41 42 private:43 ITextService * m_pTxtService;44 SOUI::CAutoRefPtr
m_ipcHandle;45 };
1 bool CClientConnection::CallFun(SOUI::IFunParams *params) const2 {3     SASSERT(m_ipcHandle);4     return m_ipcHandle->CallFun(params);5 }
1 void CSinstarProxy::ProcessKeyStoke(UINT64 imeContext, UINT vkCode, LPARAM lParam, BOOL bKeyDown, BYTE byKeyState[256], BOOL * pbEaten) 2 { 3     Param_ProcessKeyStoke param; 4     param.lpImeContext = imeContext; 5     param.vkCode = vkCode; 6     param.lParam = (DWORD)lParam; 7     param.bKeyDown = bKeyDown; 8     memcpy(param.byKeyState, byKeyState, 256); 9     param.bEaten = false;10     m_conn.CallFun(&param);11     *pbEaten = param.bEaten;12 }
CSinstarProxy对象有一个CClientConnection对象:m_conn,它需要调用服务器的方法ProcessKeyStoke,我们需要把对应的函数参数包装到对象:Param_ProcessKeyStoke中,调用m_conn.CallFun(&param),再从参数中获取返回值。

 在CClientConnection对象中有一组FUN_BEGIN,FUN_END包装的处理函数映射表,分别用来处理服务端对客户端的函数调用。

如此,一个客户端服务器双向调用的IPC就完成了。

这个IPC核心就是用参数对象来包装参数列表并经过序列化,反序列化来实现跨进程函数调用,并通过实现一些宏简化开发,美化代码结构,目前在我的启程输入法3.0中工作很好。

启程输入法3.0 GIT仓库: https://gitee.com/setoutsoft/sinstar3

 

启程软件 2019-02-03

转载于:https://www.cnblogs.com/setoutsoft/p/10350364.html

你可能感兴趣的文章
UICollectionView/ UITableView选中某一组的一个cell,其它cell不选中处理
查看>>
杨泽业:解决wordpress博客建立数据库连接时出错的问题
查看>>
关于安卓的退出
查看>>
Adaboost
查看>>
nodejs 中如何使用log4js
查看>>
Extjs Tree增加搜索功能
查看>>
浏览器内核揭秘
查看>>
学习笔记 124: 预备知识总结
查看>>
MySQL-MySQL索引原理深入剖析
查看>>
Mybatis源码-XXXmapper.xml中的resultMap标签解析过程
查看>>
db-link创建过程
查看>>
MS UC 2013-0-虚拟机-标准化-部署-2-模板机-制作-1-部署-虚拟机
查看>>
JAVA性能测试初体验
查看>>
【迁移2015-09-23 19:46】HTTPSQS(二)
查看>>
IOS 在.m文件中改变XIB中控件位置
查看>>
PLSQL连接ORACLE需要配置些什么
查看>>
Open××× 使用"用户名/密码"登录验证
查看>>
CentOS5.6下使用pptp架设***
查看>>
“锁定”语句 lock(C# 参考)
查看>>
TCP-IP协议详解(10) TCP滑窗管理
查看>>