您的位置:首页 > 其它

DynamicLinkLibraryAPI

2014-04-17 13:22 399 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: