DynamicLinkLibraryAPI

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;
}












你可能感兴趣的:(DynamicLinkLibraryAPI)