观察者方式实现动态库调用

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

以上是关于观察者方式实现动态库调用的主要内容,如果未能解决你的问题,请参考以下文章

多版本动态库的变量测试

多版本动态库的变量测试

C++中动态库调用动态库如何调用啊

Android怎么调用第三方SO动态链接库

(71)C#里怎么样调用C++动态连接库的代码

(71)C#里怎么样调用C++动态连接库的代码