1. 程式人生 > >觀察者方式實現動態庫調用

觀察者方式實現動態庫調用

方式 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 #pragma
once 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 void
UseCallBack(); 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

觀察者方式實現動態庫調用