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