DynamicLinkLibraryAPI.h
尝试使用,动态链接库技术,来实现脚本刷新。
#pragma once
#if defined(WIN32) || defined(WIN64)
#include <Windows.h>
typedef HINSTANCE DLLHANDLER;
#elif defined(__linux__)
#include <dlfcn.h>
typedef void* DLLHANDLER;
#endif
namespace dll {
// 打开动态链接库。
bool OpenDLL(DLLHANDLER* pDLLHander, const char* path
#if defined(__linux__)
, int mode = RTLD_NOW
#endif
);
// 通过名称获得动态链接库中的函数或变量地址。
void* GetDLL(DLLHANDLER* pDLLHander, const char* name);
// 关闭动态链接库
bool CloseDLL(DLLHANDLER* pDLLHander);
}
DynamicLinkLibraryAPI.cpp
#include "DynamicLinkLibraryAPI.h"
#include <stdio.h>
namespace dll {
bool OpenDLL(DLLHANDLER* pDLLHander, const char* path
#if defined(__linux__)
, int mode
#endif
) {
if (!pDLLHander || !path) {
#ifndef NDEBUG
printf("\n=====================================================\n");
printf("\tDEBUG:\n%s[%d]%s\t", __FILE__, __LINE__, "openDLL fial: null args");
printf("\n=====================================================\n");
#endif
return false;
}
#if defined(WIN32) || defined(WIN64)
*pDLLHander = LoadLibrary(path);
#elif defined(__linux__)
*pDLLHander = dlopen(path, mode);
#endif
#ifndef NDEBUG
#if defined(WIN32) || defined(WIN64)
printf("\n=====================================================\n");
printf("\tDEBUG:\n%s[%d]path=[%s]\t", __FILE__, __LINE__, path);
printf("\n=====================================================\n");
#elif defined(__linux__)
printf("\n=====================================================\n");
printf("\tDEBUG:\n%s[%d]path=[%s] mode=[%d]\t", __FILE__, __LINE__, path, mode);
printf("\n=====================================================\n");
#endif
#endif
return pDLLHander != nullptr;
}
void* GetDLL(DLLHANDLER* pDLLHander, const char* name) {
if (!pDLLHander || !name) {
#ifndef NDEBUG
printf("\n=====================================================\n");
printf("\tDEBUG:\n%s[%d]%s\t", __FILE__, __LINE__, "getDLL fial: null args");
printf("\n=====================================================\n");
#endif
return nullptr;
}
#if defined(WIN32) || defined(WIN64)
return GetProcAddress(*pDLLHander, name);
#elif defined(__linux__)
return dlsym(*pDLLHander, name);
#endif
}
bool CloseDLL(DLLHANDLER* pDLLHander) {
bool flag = false;
if (pDLLHander) {
#if defined(WIN32) || defined(WIN64)
flag = FreeLibrary(*pDLLHander);
#elif defined(__linux__)
flag = (dlclose(*pDLLHander) == 0);
#endif
}
#ifndef NDEBUG
if (flag) {
printf("\n=====================================================\n");
printf("\tDEBUG:\n%s[%d] %s\t", __FILE__, __LINE__, "closeDLL succ");
printf("\n=====================================================\n");
} else {
printf("\n=====================================================\n");
printf("\tDEBUG:\n%s[%d] %s\t", __FILE__, __LINE__, "closeDLL fail");
printf("\n=====================================================\n");
}
#endif
return flag;
}
}
DynamicLinkLibraryMgr.h
#pragma once
#include "DynamicLinkLibraryAPI.h"
#include <ostream>
#include <set>
#include <map>
#include <ctime>
#include <string.h>
#include <iostream>
// 创建已知类型的脚本函数类,及对象。
#define SCRIPTCLASS(NAME, DEFFUN) \
class C##NAME { \
protected: \
typedef DEFFUN; \
\
static C##NAME* m_Instance; \
\
C##NAME() { \
m_pScripts = new std::set<DEF>; \
} \
public: \
\
bool operator==(const C##NAME& ref) { \
return m_Version == ref.m_Version; \
} \
\
static C##NAME* Instance() { \
if (!m_Instance) { \
m_Instance = new C##NAME; \
} \
return m_Instance; \
} \
\
const double GetVersion() const { \
return m_Version; \
} \
\
void SetVersion(double version) { \
m_Version = version; \
} \
\
const time_t GerCtime() const { \
return m_Ctime; \
} \
\
bool Reg(DLLHANDLER* dllHandler, const char* name) { \
void* p = dll::GetDLL(dllHandler, name); \
if (!p) { \
std::cout << "can not find " << name << " dll fun" << std::endl; \
return false; \
} \
if (p) { \
m_pScripts->insert((DEF)p); \
} \
return true; \
} \
\
std::set<DEF>* GetScripts() { \
return this->m_pScripts; \
} \
\
void Clear() { \
this->m_pScripts->clear(); \
} \
private: \
double m_Version; \
time_t m_Ctime; \
std::set<DEF>* m_pScripts; \
}; \
C##NAME* C##NAME::m_Instance = nullptr; \
// 动态函数
class CDynamicLinkFun {
// 类中声明
friend std::ostream& operator<<(std::ostream& os, const CDynamicLinkFun& ref);
public:
CDynamicLinkFun(const char* name, const char* tname, void* fun) ;
private:
char m_Name[64];
char m_Tname[128];
void* m_Fun;
time_t m_Ctime;
};
class CDynamicLinkLibrary {
public:
CDynamicLinkLibrary(const char* name, const char* path) ;
~CDynamicLinkLibrary() ;
// 获得动态库地址
const char* GetPath() const ;
// 设置动态库地址
void SetPath(const char* path) ;
// 初始化
bool Init() ;
// 销毁
bool Destory() ;
// 重新加载
bool Reload() ;
private:
// 库名称
char m_Name[64];
// 库地址
char m_Path[128];
// 加载时间
time_t m_Ctime;
// 该动态库中的所有函数
std::map<const char*, CDynamicLinkFun*> m_Scripts;
// 动态链接库描述
DLLHANDLER* m_pDLLHander;
// 状态:0为默认,1为已初始化
int m_State;
};
class CDynamicLinkLibraryMgr {
public:
// 重新加载所有
int reloadDLLs();
};
DynamicLinkLibraryMgr.cpp
#include "DynamicLinkLibraryMgr.h"
// 类外定义
std::ostream& operator<<(std::ostream& os, const CDynamicLinkFun& ref) {
os << " Name:" << ref.m_Name << " TName:" << ref.m_Tname << " Address:" << std::showpoint << ref.m_Fun;
return os;
}
CDynamicLinkFun::CDynamicLinkFun(const char* name, const char* tname, void* fun) {
strcpy(m_Name, name);
strcpy(m_Tname, tname);
m_Fun = fun;
time(&m_Ctime);
}
CDynamicLinkLibrary::CDynamicLinkLibrary(const char* name, const char* path) {
m_State = 0;
m_pDLLHander = new DLLHANDLER;
strcpy(m_Name, name);
strcpy(m_Path, path);
time(&m_Ctime);
}
CDynamicLinkLibrary::~CDynamicLinkLibrary()
{
Destory();
m_pDLLHander = nullptr;
}
const char* CDynamicLinkLibrary::GetPath() const {
return this->m_Path;
}
void CDynamicLinkLibrary::SetPath(const char* path) {
strcpy(m_Path, path);
}
bool CDynamicLinkLibrary::Init() {
if (m_State) {
#ifndef NDEBUG
printf("\n=====================================================\n");
printf("\tDEBUG:\n%s[%d] %s\t", __FILE__, __LINE__, "动态链接库已初始化,无法再初始化!");
printf("\n=====================================================\n");
#endif
return false;
}
if (dll::OpenDLL(m_pDLLHander, m_Path)) {
m_State = 1;
// void GetScripts(std::map<const char*, const char*>& scripts)
void (*GetScripts)(std::map<const char*, const char*>& scripts) = reinterpret_cast<void (*) (std::map<const char*, const char*>& scripts)>(dll::GetDLL(m_pDLLHander, "GetScripts"));
if (!GetScripts) {
return false;
}
std::map<const char*, const char*> __map;
GetScripts(__map);
for (auto kv : __map) {
std::cout << kv.first << " " << kv.second << std::endl;
#ifndef NDEBUG
bool flag = true;
#endif
if (strlen(kv.first) > 0 && strlen(kv.second) > 0) {
void* fun = dll::GetDLL(m_pDLLHander, kv.first);
if (fun) {
m_Scripts.insert(std::make_pair(kv.first, new CDynamicLinkFun(kv.first, kv.second, fun)));
#ifndef NDEBUG
flag = false;
#endif
}
}
#ifndef NDEBUG
if (flag) {
printf("\n=====================================================\n");
printf("\tDEBUG:\n%s[%d]%s %s %s\t", __FILE__, __LINE__, "load function fail", kv.first, kv.second);
printf("\n=====================================================\n");
}
#endif
}
std::cout << "\n---------------------------" << std::endl;
#ifndef NDEBUG
for (auto kv : m_Scripts) {
std::cout << *(kv.second) << std::endl;
}
#endif
return true;
}
return false;
}
bool CDynamicLinkLibrary::Destory() {
if (!m_State) {
#ifndef NDEBUG
printf("\n=====================================================\n");
printf("\tDEBUG:\n%s[%d] %s\t", __FILE__, __LINE__, "动态链接库尚未初始化,无法销毁!");
printf("\n=====================================================\n");
#endif
return false;
}
bool rt = dll::CloseDLL(m_pDLLHander);
if (rt) {
m_State = 0;
}
for (auto kv : m_Scripts) {
kv.second = nullptr;
}
m_Scripts.clear();
return rt;
}
bool CDynamicLinkLibrary::Reload() {
Destory();
return Init();
}
min.cpp
#include "DynamicLinkLibraryMgr.h"
#include <iostream>
#include <thread>
#include <fstream>
#include <string>
#include <string.h>
#if defined(WIN32) || defined(WIN64)
#define path "../Debug/SayHello.dll"
#elif defined(__linux__)
#define path "../Debug/SayHello.so"
#endif
bool bReload = true;
char path2[126] = {0};
int test(DLLHANDLER* pHandler);
int reload(DLLHANDLER* pHandler);
// SCRIPTCLASS(LoginPreScript, void (*DEF) (void*) )
int main(int argc, char **argv) {
CDynamicLinkLibrary* pDynamicLinkLibrary = nullptr;
if (argc == 2) {
strcpy(path2, argv[1]);
std::cout << "path2 " << path2 << std::endl;
pDynamicLinkLibrary = new CDynamicLinkLibrary("test" ,path2);
} else {
pDynamicLinkLibrary = new CDynamicLinkLibrary("test", path);
}
pDynamicLinkLibrary->Init();
return 0;
}
//
// int main(int argc, char **argv) {
//
// if (argc == 2) {
// strcpy(path2, argv[1]);
// std::cout << "path2 " << path2 << std::endl;
// }
//
// DLLHANDLER* pHandler = new DLLHANDLER;
// std::thread t(
// [&pHandler](){
//
// for (;;) {
// test(pHandler);
// }
// }
// );
// t.detach();
//
// for (;;) {
//
// std::string str;
// std::getline(std::cin, str);
// strcpy(path2, str.c_str());
// std::cout << "path2 " << path2 << std::endl;
// reload(pHandler);
//
//
// }
//
// return 0;
// }
//
// int reload(DLLHANDLER* pHandler) {
// bReload = true;
// return dll::CloseDLL(pHandler);
// }
//
// int test(DLLHANDLER* pHandler) {
//
// std::cout << "bReload :: " << std::boolalpha << bReload << std::endl;
// std::cout << "path2 :: " << path2 << std::endl;
// if (bReload) {
// bReload = false;
//
// bool ret = false;
// if (strlen(path2) > 0) {
// ret = dll::OpenDLL(pHandler, path2);
// } else {
// ret = dll::OpenDLL(pHandler, path);
// }
//
// if (!ret) {
// std::cout << "can not open dll" << std::endl;
// return -1;
// }
//
// CLoginPreScript::Instance()->Clear();
// CLoginPreScript::Instance()->Reg(pHandler, "loginPre1");
// CLoginPreScript::Instance()->Reg(pHandler, "loginPre2");
//
// }
//
// auto scripts = CLoginPreScript::Instance()->GetScripts();
// for (auto loginpre = scripts->begin(); loginpre != scripts->end(); loginpre++) {
// (*loginpre)(nullptr);
// }
//
//
// // bool ret = dll::closeDLL(pHandler);
// // if (ret) {
// // std::cout << "关闭成功" << std::endl;
// // } else {
// // std::cout << "关闭失败" << std::endl;
// // }
// //
// // ret = dll::openDLL(pHandler, path);
// // if (!ret) {
// // std::cout << "打开动态链接库失败" << std::endl;
// // return -1;
// // }
//
//
// //
// //
// // void* p = dll::getDLL(pHandler, "add");
// // if (!p) {
// // std::cout << "can not get dll method" << std::endl;
// // return -2;
// // }
// //
// // int (*addFun)(int, int) = (int(*)(int, int))p;
// // int sum = addFun(1, 8);
// //
// // std::cout << "sum = " << sum << std::endl;
// //
// //
// // void* p2 = dll::getDLL(pHandler, "add2");
// // if (!p2) {
// // std::cout << "can not get dll method" << std::endl;
// // return -3;
// // }
// //
// // int (*add2Fun)(int, int, int) = (int(*)(int, int, int))p2;
// // int sum2 = add2Fun(1, 8, 10);
// //
// // std::cout << "sum2 = " << sum2 << std::endl;
// //
// //
// // void* p3 = dll::getDLL(pHandler, "sayHello");
// // if (!p3) {
// // std::cout << "can not get dll method" << std::endl;
// // return -4;
// // }
// // void (*sayHelloFun)() = (void(*)()) p3;
// //
// // sayHelloFun();
// //
// // void* (*getUser)() = (void* (*)()) dll::getDLL(pHandler, "getUser");
// //
// // void* pU = getUser();
// //
// // void (*printUser)(void*) = (void (*)(void*)) dll::getDLL(pHandler, "printUser");
// //
// // printUser(pU);
// //
// // #if defined(WIN32) || defined(WIN64)
// // #elif defined(__linux__)
// // char** name = (char**) dll::getDLL(pHandler, "name");
// // int* age = (int*) dll::getDLL(pHandler, "age");
// // std::cout << *name << std::endl;
// // std::cout << *age << std::endl;
// //
// // #endif
//
// std::this_thread::sleep_for(std::chrono::seconds(10));
//
// return 1;
//
// }
以下是动态链接库项目:
DynamicLinkLibraryScript.cpp
#include <map>
#ifndef DLL_API
#if defined(WIN32) || defined(WIN64)
#define DLL_API __declspec(dllexport)
#elif defined(__linux__)
#define DLL_API
#endif
#endif
extern "C" DLL_API void GetScripts(std::map<const char*, const char*>& scripts) {
scripts.insert(std::make_pair("loginPre1", "void (*loginPre1)(void*)"));
scripts.insert(std::make_pair("loginPre2", "void (*loginPre2)(void*)"));
scripts.insert(std::make_pair("add", "int (*add)(int ,int )"));
scripts.insert(std::make_pair("add2", "int (*add2)(int , int , int )"));
scripts.insert(std::make_pair("sayHello", "void (*sayHello)()"));
scripts.insert(std::make_pair("getUser", "void* (*getUser)()"));
scripts.insert(std::make_pair("printUser", "void (*printUser)(void*)"));
}
LoginPreScript.cpp
#include <iostream>
// void (*LoginPre) (void*)
#ifndef DLL_API
#if defined(WIN32) || defined(WIN64)
#define DLL_API __declspec(dllexport)
#elif defined(__linux__)
#define DLL_API
#endif
#endif
extern "C" DLL_API void loginPre1(void* p) {
std::cout << "loginPre1 yyyyyy" << std::endl;
}
extern "C" DLL_API void loginPre2(void* p) {
std::cout << "loginPre2 xxxxxx" << std::endl;
}
Math.h
#pragma once
#ifndef DLL_API
#if defined(WIN32) || defined(WIN64)
#define DLL_API __declspec(dllexport)
#elif defined(__linux__)
#define DLL_API
#endif
#endif
extern "C" int DLL_API add(int x,int y);
Math.cpp
#include "Math.h"
int add(int x,int y) {
return x + y;
}
Math2.cpp
#ifndef DLL_API
#if defined(WIN32) || defined(WIN64)
#define DLL_API __declspec(dllexport)
#elif defined(__linux__)
#define DLL_API
#endif
#endif
extern "C" int DLL_API add2(int i, int j, int k) {
return i + j + k + 100000;
}
SayHello2.cpp
#include <iostream>
#include <string.h>
#ifndef DLL_API
#if defined(WIN32) || defined(WIN64)
#define DLL_API __declspec(dllexport)
#elif defined(__linux__)
#define DLL_API
#endif
#endif
char* name = "jack";
int age = 27;
extern "C" DLL_API void sayHello() {
std::cout << "hello 3!" << name << age << std::endl;
}
class User {
// 类中声明
friend std::ostream& operator<<(std::ostream& os, const User& ref);
public:
User(const char* username, const char* password) {
strcpy(this->username, username);
strcpy(this->password, password);
}
const char* getUsername() const {
return this->username;
}
const char* getPassword() const {
return this->password;
}
private:
char username[64];
char password[64];
};
// 类外定义
std::ostream& operator<<(std::ostream& os, const User& ref) {
os << ref.username << " " << ref.password;
return os;
}
User* pU = new User("jack", "pswd");
extern "C" DLL_API User* getUser() {
return pU;
}
extern "C" DLL_API void printUser(User* u) {
std::cout << *u << std::endl;
}