观察者方式实现动态库调用
Posted liquid
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了观察者方式实现动态库调用相关的知识,希望对你有一定的参考价值。
最近在项目中,经常用到使用对方提供框架,由自己提供动态库实现的形式,找个空闲的时间讲大概的流程阐述出来,一是为近期的工作总结,二是想获得大家的一些批评和指正。
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: 无法解析的外部符号 [email protected],该符号在函数 ___tmainCRTStartup 中被引用
解决方案:见 https://blog.csdn.net/playstudy/article/details/6661868
以上是关于观察者方式实现动态库调用的主要内容,如果未能解决你的问题,请参考以下文章