zoukankan      html  css  js  c++  java
  • 插件设计

    插件设计

    我们只需要在dll里面在继承这个虚基类  进行实现  便可实现com的设计

    但是需要dll导出一个函数  这个函数的功能便是返回一个基类指针  子类对象的指针  这样在实

    际使用中我们只需要获取一个对象指针  直接使用其功能程序便会自动查虚表进行调用子类实现的

    功能  这样便实现了导出一个函数  可以使用各种功能的设计

    装插件的时机一般在产生窗口后产生create消息来临的时候安装插件

    c++版插件设计
    之前c插件设计是在结构体中保存函数的地址。把结构体的指针传过来。
    c++则是利用虚表的结构来实现的,通过返回类对象来查找对应的虚表函数。
    
    通过继承纯虚基类实现函数的代码
    class IShape
    {
    public:
      virtual const char* MY_CALL GetPuinName() = 0;
      virtual int MY_CALL OnSetBeginPoint(POINT pt) = 0;
      virtual int MY_CALL OnSetEndPoint(POINT pt) = 0;
      virtual int MY_CALL OnDraw(HDC hdc) = 0;
      virtual int Release() = 0;
    };
    //返回类的对象来拿到虚表指针
      IShape* MY_CALL MyGetClassObject();
    //定义函数指针来方便调用
      typedef IShape*  (MY_CALL *MY_GET_CLASS_OBJECT)();
    //拿到函数指针
      MY_GET_CLASS_OBJECT pfnGetClassObj = (MY_GET_CLASS_OBJECT)GetProcAddress(hModule, "MyGetClassObject");
    //拿到类对象
      IShape *pObject = pfnGetClassObj();
    //添加类对象
     g_interfaces.push_back(pObject);
    //因为对象都是new出来的,所以要考虑到释放问题,只是放自己却不能影响到其他类,所以不能等析构,不然父类也会释放。释放时间WM_DESTROY消息:
      g_interfaces[i]->Release();
      //自杀
      virtual int Release()
      {
        delete this;
        return 0;
      }

    原来的版本

    在插件里导出函数

    一般有  插件名和函数

    应用程序中 :识别插件添加到菜单中

    首先遍历插件目录,查找所以的插件,然后添加到菜单当中

     //加载插件
      WIN32_FIND_DATA FileData;
      HANDLE hSearch = FindFirstFile("./plugin/*.dll", &FileData);
    //如果有dll文件,专门为dll文件做一个主菜单 设置菜单名
      InsertMenu(hMenu, 1, MF_BYPOSITION | MF_POPUP, (UINT_PTR)hMenu, "Shape(&S)");
    
    //定义子菜单
      HMENU hSubMenu = GetSubMenu(hMenu, 1);
    
      BOOL fFinished = TRUE;
      while (fFinished)
      {
    相对路径加上文件名
        std::string path("./plugin/");
        path += FileData.cFileName;
    
        CadInterface interface;
        //加载插件
        HMODULE hModule = LoadLibrary(path.c_str());
        if (hModule != nullptr)
    {
    这里需要拿所有的函数指针。遍历函数指针
          for (int i = 0; i < sizeof(g_funName) / sizeof(g_funName[0]); i++)
          {
    这里定义一个结构体,将函数名和指针定义一起,每次就一起拿。无需判断看下图特别说明
            interface.interface[i].pfn = GetProcAddress(hModule, g_funName[i]);
          }
    这里需要判断是不是插件,如果函数名为空就不添加菜单继续遍历下一个dll
          if (interface.interface[0].pfn != nullptr)
          {
            g_interfaces.push_back(interface);
    //添加子菜单,参数:句柄,类型(加入的方式),设置id,菜单名。菜单名用插件定义的
            AppendMenu(hSubMenu, MF_STRING, WM_USER + index++,                          
    interface.interface[0].CR33CadGetPuinName());
          }
        }
    获取下一个文件信息
        fFinished = FindNextFile(hSearch, &FileData);
      }
    关闭HANDLE
      FindClose(hSearch);

    因为大量的操作在应用中,使用起来很不方便,所以我们在插件中只提供一个数组指针保存着所有函数的地址,应用程序只用加载一个函数就可以了

    vector<CadInterface*> g_interfaces; //所有插件接口  将插件用动态数组指针保存起来

    插件头文件需要定义一个数组 来保存所有函数类型的定义,方便使用

    //接口不变原则
    struct CadInterface
    {
        const char* (__stdcall *GetPuinName)();
        int (__stdcall *OnSetBeginPoint)(POINT pt);
        int(__stdcall *OnSetEndPoint)(POINT pt);
        int (__stdcall *OnDraw)(HDC hdc);
        void(__stdcall *New)();
    };
    定义宏为导出函数重命名
    #define CAD_INTERFACE extern "C" __declspec(dllexport) CadInterface g_interfaces
    应用中
          interface = (CadInterface*)GetProcAddress(hModule, "g_interfaces");
    在dll中
    
    实现函数指针的值就行了
    一般在函数后面都会加入默认参数以防以后需要改变。或者加入函数指针以防添加 多参(void *p)
    
    定义结构体指针
    struct CadInterface
    {
        const char* (__stdcall *GetPuinName)();
        int (__stdcall *OnSetBeginPoint)(POINT pt);
        int(__stdcall *OnSetEndPoint)(POINT pt);
        int (__stdcall *OnDraw)(HDC hdc);
        void(__stdcall *New)();
    };
    定义结构体指针对象。并在dll中实现
    CadInterface g_interfaces= {
      GetPuinName , 
      OnSetBeginPoint, 
      OnSetEndPoint, 
      OnDraw,
      New
     };
    学如逆水行舟,不进则退。 博客园技术交流群 群 号:1073255314 (本群没人,刚刚建立 -_-!!! )
  • 相关阅读:
    对象的引用
    查询各个商品分类中各有多少商品的SQL语句
    将TP引擎改为smarty引擎
    图片预加载
    js中接口的声明与实现
    判断对象是否是某个类的实例
    判断变量是否为json对象
    Python 爬取淘宝商品数据挖掘分析实战
    Python 爬取淘宝商品数据挖掘分析实战
    扫盲丨关于区块链你需要了解的所有概念
  • 原文地址:https://www.cnblogs.com/Mj-NaijAm/p/13602368.html
Copyright © 2011-2022 走看看