天天看點

linux和windows下動态連結庫調用類

LibSo.h

#pragma once

typedef void* HANDLE;
typedef void* ProcAddr;

#include <string>

namespace COMMON
{
	namespace UTILITY
	{
		class LibSo
		{
		public:
			LibSo();
			virtual ~LibSo();
			static HANDLE LoadLib(const std::string& path);
			static void FreeLib(HANDLE hHandle);
			static ProcAddr GetProcAddr(HANDLE hHandle, const std::string& proName);
		};
	}
}
           

LibSo.cpp

#include "LibSo.h"
#if defined(_WIN32) || defined(_WIN64)
#include <winsock2.h>
#include <windows.h>
#elif defined(__linux__)
#include <dlfcn.h>
#endif

namespace COMMON
{
	namespace UTILITY
	{
		LibSo::LibSo()
		{
		}
		
		LibSo::~LibSo()
		{
		}

		HANDLE LibSo::LoadLib(const std::string& path)
		{
#if defined(_WIN32) || defined(_WIN64)
			HMODULE h = NULL;
			char szPath[MAX_PATH] = {0};
			char * p = NULL;

			if (path.empty())
			{
				return nullptr;
			}

			//replace '/' by '\\' if exist '/'.
#if (_MSC_VER >= 1500 && !defined _WIN32_WCE)
			strcpy_s(szPath, MAX_PATH, path.c_str());
#else
			strcpy(szPath, path.c_str());
#endif

			p = szPath;
			while ((p = strchr(p, '/')) != NULL)
			{
				*p = '\\';
			}

#if defined _WIN32_WCE
			wchar_t wPath[260] = { 0 };
			MultiByteToWideChar(CP_ACP, 0, szPath, strlen(szPath), wPath, sizeof(wPath));
			h = LoadLibraryEx(wPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
#else
			h = LoadLibraryEx(szPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
#endif
			if (h == NULL)
			{
#if defined _WIN32_WCE
				h = LoadLibraryEx(wPath, NULL, 0);
#else
				DWORD ret = GetLastError();
				h = LoadLibraryEx(szPath, NULL, 0);
#endif
			}

			return h;
#elif defined(__linux__)

			if (path.empty())
			{
				return nullptr;
			}

			HANDLE dlsm = dlopen(path.c_str(), RTLD_LAZY);
			char* iErr = nullptr;
			if (dlsm == nullptr)
			{
				iErr = dlerror();
				printf("load failed: %s\n", iErr);
			}
			return dlsm;
#endif
		}

		void LibSo::FreeLib(HANDLE hHandle)
		{
#if defined(_WIN32) || defined(_WIN64)
			if ((hHandle != nullptr) && (FreeLibrary((HMODULE)hHandle)))
			{
				return;
			}
#elif defined(__linux__) || defined(__APPLE__)
			if ((hHandle) && (!dlclose(hHandle)))
			{
				return;
			}
#endif

		}

		ProcAddr LibSo::GetProcAddr(HANDLE hHandle, const std::string& proName)
		{
#if defined(_WIN32) || defined(_WIN64)
			if (hHandle == nullptr || proName.empty())
			{
				return nullptr;
			}

#if defined _WIN32_WCE
			return (ProcAddr)GetProcAddressA((HMODULE)hHandle, proName.c_str());
#else
			return (ProcAddr)GetProcAddress((HMODULE)hHandle, proName.c_str());
#endif
#elif defined(__linux__)
			if ( hHandle != nullptr && !proName.empty() )
			{
				return (ProcAddr)dlsym(hHandle, proName.c_str());
			}

			return NULL;
#endif
		}
	}
}
           

編譯時要加上 -ldl 選項 ,以産生可調用動态連結庫的執行代碼。

main.cpp

#include "LibSo.h"
#include<iostream>

#if defined(WIN32) || defined(WIN64)
	#define CALLBACK __stdcall
#else
	#define CALLBACK 
#endif
typedef long  (CALLBACK* Protocol_Init)();

int main(void)
{	
	std::string path;
#if defined(WIN32) || defined(WIN64)
	path = "test.dll";
#else
	path = "test.so"; //假設test動态連結庫裡有Protocol_Init函數
#endif

	HANDLE hDllModule;
	hDllModule= COMMON::UTILITY::LibSo::LoadLib(path);
	Protocol_Init= reinterpret_cast<Protocol_Init>(COMMON::UTILITY::LibSo::GetProcAddr(hDllModule, "Protocol_Init"));
	if (nullptr == m_funcProtocol_Init)
	{
		printf("Protocol_Init function is Null!\n");
		result = false;
	}
	
	if(Protocol_Init)
	{
		Protocol_Init();//調用test動态庫裡面的Protocol_Init函數
	}
		
	COMMON::UTILITY::LibSo::FreeLib(hDllModule);//釋放
	
	return 0;
}


           

繼續閱讀