插件Demo
main #include <vector> #include <string> #include <iostream> #include <windows.h> using namespace std; // 1. 插件通常是以什么样的方式存在的 // - 通常是以 dll 的方式存在的,但是后缀名可能会有变化 // 2. 应用程序如何找到所有的插件 // - 所有的插件都应该被保存到具体的路径中 // 3. 应用程序怎样知道是否符合自己的要求 // - 插件必须提供指定名称的函数说明自己的信息 // - 插件还需要通过对应名称的函数提供具体的功能 struct PluginInfo { HMODULE Handle; char name[20]; char ver[20]; }; using queryInfo = bool(*)(char* name, char* ver); using clearPlugin = void(*)(); using runPlugin = void(*)(); // 用于保存所有的插件信息 vector<PluginInfo> PluginVec; // 加载插件,获取插件的基本信息,并且判断插件是否是有效的 void init() { WIN32_FIND_DATA FileData = { 0 }; // 1. 遍历当前指定的插件目录,获取插件 HANDLE Handle = FindFirstFile("./plugins/*.plg", &FileData); if (Handle != INVALID_HANDLE_VALUE) { do { PluginInfo info = { 0 }; string path("./plugins/"); path = path + FileData.cFileName; // 2. 加载找到的对应格式的文件 info.Handle = LoadLibraryA(path.c_str()); // 3. 通过指定函数获取插件的信息 queryInfo func = (queryInfo)GetProcAddress(info.Handle, "queryInfo"); // 4. 获取信息 bool b = func(info.name, info.ver); if (b == true) { PluginVec.push_back(info); printf("name: %s[%s]\n", info.name, info.ver); } } while (FindNextFile(Handle, &FileData)); } } // 调用插件提供的函数,实现相应的功能 void running() { for (auto& info : PluginVec) { // 调用插件的功能函数 runPlugin func = (runPlugin)GetProcAddress(info.Handle, "runPlugin"); if (func) func(); } } // 卸载插件,执行清理 void exit() { for (auto& info : PluginVec) { // 卸载之前,应该调用插件的函数,执行插件的清理 clearPlugin func = (clearPlugin)GetProcAddress(info.Handle, "clearPlugin"); if (func) func(); FreeLibrary(info.Handle); } } int main() { init(); running(); exit(); return 0; }
dllmain.cpp
// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "framework.h" #include <stdio.h> BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } bool queryInfo(char* name, char* ver) { memcpy(name, "plgin_one", 10); memcpy(ver, "0.0.0.0.1", 10); return true; } void clearPlugin() { printf("plgin_one[0.0.0.0.1]正在清理插件\n"); } void runPlugin() { printf("plgin_one[0.0.0.0.1]正在运行插件\n"); }
framework.h
// header.h: 标准系统包含文件的包含文件, // 或特定于项目的包含文件 // #pragma once #define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 // Windows 头文件 #include <windows.h> extern "C" _declspec(dllexport) bool queryInfo(char* name, char* ver); extern "C" _declspec(dllexport) void clearPlugin(); extern "C" _declspec(dllexport) void runPlugin();