觀察者方式實現動態庫調用
阿新 • • 發佈:2019-03-31
方式 adl avi span RoCE dash lin lba 觀察
最近在項目中,經常用到使用對方提供框架,由自己提供動態庫實現的形式,找個空閑的時間講大概的流程闡述出來,一是為近期的工作總結,二是想獲得大家的一些批評和指正。
1、外單位提供了一個程序的基礎框架,其中實現應該相當復雜,我這裏只能做一個大概的猜測。
主程序如下,調用了其自身的主動態庫:
1 int main() 2 { 3 HINSTANCE hDll = LoadLibraryA("TestObserver.dll"); 4 system("pause"); 5 return 0; 6 }
采用單件和觀察者模式實現主動態庫管理類:
1 #pragmaonce 2 #include "TestObserver_export.h" 3 #include "global_api.h" 4 5 class CDllMgr 6 { 7 public: 8 ~CDllMgr(void); 9 10 static CDllMgr* GetInstance(); //獲取單件實例 11 12 void Attach(CObserverInterface* handel); //註冊觀察者 13 14 void Detach(); //釋放 15 16 voidUseCallBack(); 17 18 private: 19 CDllMgr(void); //聲明構造函數為private 20 CObserverInterface* m_handel; 21 };
1 #include "StdAfx.h" 2 #include "DllMgr.h" 3 4 CDllMgr::CDllMgr(void) 5 { 6 } 7 8 9 CDllMgr::~CDllMgr(void) 10 { 11 Detach(); 12 } 13 14 CDllMgr* CDllMgr::GetInstance()15 { 16 static CDllMgr instance; 17 return &instance; 18 } 19 20 void CDllMgr::Attach(CObserverInterface* handel) 21 { 22 m_handel = handel; 23 } 24 25 void CDllMgr::Detach() 26 { 27 if (m_handel != NULL) 28 { 29 delete m_handel; 30 } 31 } 32 33 void CDllMgr::UseCallBack() 34 { 35 m_handel->CallBackTest(); 36 }
提供給用戶一些接口,以供主框架回調:
1 #ifndef global_api_h__ 2 #define global_api_h__ 3 4 #include "TestObserver_export.h" 5 6 class TEST_OBSERVER_API CObserverInterface 7 { 8 public: 9 virtual void CallBackTest() = 0; //用戶繼承接口並實現 10 }; 11 12 void TEST_OBSERVER_API AttachMgr(CObserverInterface* handel); //用戶註冊觀察者 13 14 #endif // global_api_h__
其中"TestObserver_export.h"為定義導出類文件:
1 #ifndef TESTOBSERVER_EXPORTS 2 #define TEST_OBSERVER_API __declspec(dllimport) 3 #else 4 #define TEST_OBSERVER_API __declspec(dllexport) 5 #endif
這裏使用dllmain.h簡單模擬主框架對用戶實現的調用
1 // dllmain.cpp : 定義 DLL 應用程序的入口點。 2 #include "stdafx.h" 3 #include <stdio.h> 4 #include "DllMgr.h" 5 6 7 BOOL APIENTRY DllMain( HMODULE hModule, 8 DWORD ul_reason_for_call, 9 LPVOID lpReserved 10 ) 11 { 12 HINSTANCE hDll = LoadLibraryA("UserDll.dll"); 13 switch (ul_reason_for_call) 14 { 15 case DLL_PROCESS_ATTACH: 16 CDllMgr::GetInstance()->UseCallBack(); 17 break; 18 case DLL_PROCESS_DETACH: 19 CDllMgr::GetInstance()->Detach(); 20 break; 21 } 22 return TRUE; 23 }
2.第二部分為用戶提供的動態庫以供主框架調用。
用戶實現了虛接口:
1 #pragma once 2 #include "../../TestObserver/TestObserver/global_api.h" 3 4 class CUserTest: 5 public CObserverInterface 6 { 7 public: 8 CUserTest(void); 9 ~CUserTest(void); 10 11 virtual void CallBackTest(); //實現虛接口 12 };
1 #include "StdAfx.h" 2 #include "UserTest.h" 3 #include <stdio.h> 4 5 CUserTest::CUserTest(void) 6 { 7 } 8 9 CUserTest::~CUserTest(void) 10 { 11 } 12 13 void CUserTest::CallBackTest() 14 { 15 printf("User define behavior"); 16 }
用戶需要利用主框架提供的全局接口對自身組件註冊觀察者:
1 // dllmain.cpp : 定義 DLL 應用程序的入口點。 2 #include "stdafx.h" 3 #include "UserTest.h" 4 5 BOOL APIENTRY DllMain( HMODULE hModule, 6 DWORD ul_reason_for_call, 7 LPVOID lpReserved 8 ) 9 { 10 if (DLL_PROCESS_ATTACH == ul_reason_for_call) 11 { 12 CUserTest test; 13 AttachMgr(&test); 14 } 15 return TRUE; 16 }
這樣當主框架起來後,用戶提供的動態庫也被調起來了。
3.回顧一下自己在實現過程中遇到的一些問題:
1、問題描述:LINK : fatal error LNK1123: 轉換到 COFF 期間失敗: 文件無效或損壞
解決方案:項目—屬性—配置屬性—清單工具—輸入輸出—嵌入清單,改為“否”。
2、問題描述:error LNK2019: 無法解析的外部符號 _wWinMain@16,該符號在函數 ___tmainCRTStartup 中被引用
解決方案:見 https://blog.csdn.net/playstudy/article/details/6661868
觀察者方式實現動態庫調用