1 Windows/Linux的动态库加载

该类用于在Windows/Linux加载动态库,并使用动态库,具体功能如下:
- 加载动态库
- 卸载动态库
- 获取动态库中接口函数指针
- 得到错误信息
- 得到动态库加载状态

Github地址 : https://github.com/HW140701/DynamicModuleLoader

2 代码

2.1 DynamicModuleLoader.h

头文件代码如下:

//!
//! @brief - Load dynamic libraries on Windows and Linux platforms
//!
//! @author - HuangWang
//!
//! @data - 2019-09-26
//!


#ifndef _DYNAMIC_MODULE_LOADER_H_
#define _DYNAMIC_MODULE_LOADER_H_

#include <string>
#include <fstream>

#define _DYNAMIC_LOAD
#define WINDOWS

#if defined(_DYNAMIC_LOAD)

#if defined(WINDOWS)
#include <Windows.h>
#define MODULE_HANDLER HINSTANCE
#elif defined(LINUX)
#include <dlfcn.h>
#define MODULE_HANDLER void*
#endif 

#endif


#ifdef WINDOWS
#define PLATFORM_PATH_SPLIT_CHAR "\\"
#define PLATFORM_DYNAMIC_LIBRARY_PRE ""
#define PLATFORM_DYNAMIC_LIBRARY_EXT ".dll"
#elif defined (LINUX)
#define PLATFORM_PATH_SPLIT_CHAR "/"
#define PLATFORM_DYNAMIC_LIBRARY_PRE "lib"
#define PLATFORM_DYNAMIC_LIBRARY_EXT ".so"
#endif // WINDOWS


namespace DynamicModuleLoaderSpace
{
    enum DynamicModuleState
    {
        DMS_UnLoaded = 0,
        DMS_Loaded = 1
    };

    class DynamicModuleLoader
    {
    public:
        DynamicModuleLoader();
        virtual ~DynamicModuleLoader();

        static bool IsFileExist(const std::string filePath);

        bool LoadDynamicModule(const std::string dynamicModulePath);

        void* GetFunction(const std::string functionName);

        bool UnloadDynamicModule();

        std::string GetErrorMessage();

        bool GetDynamicModuleState();
    private:
        void GetInternalErrorMessge(int errorCode);
    private:
        MODULE_HANDLER m_DynamicModulePtr;

        std::string m_ErrorMessage;

        DynamicModuleState m_DynamicModuleState;
    };
}


#endif /// _DYNAMIC_MODULE_LOADER_H_

cpp代码如下:

#include "DynamicModuleLoader.h"

namespace DynamicModuleLoaderSpace
{
    DynamicModuleLoader::DynamicModuleLoader() :m_DynamicModulePtr(NULL), m_ErrorMessage(""), m_DynamicModuleState(DynamicModuleState::DMS_UnLoaded)
    {
    }

    DynamicModuleLoader::~DynamicModuleLoader()
    {
    }

    bool DynamicModuleLoader::IsFileExist(const std::string filePath)
    {
        std::fstream file;
        file.open(filePath, std::ios::in);
        if (file)
        {
            file.close();
            return true;
        }
        else
        {
            return false;
        }
    }

    bool DynamicModuleLoader::LoadDynamicModule(const std::string dynamicModulePath)
    {
        if (IsFileExist(dynamicModulePath))
        {
#ifdef WINDOWS
            m_DynamicModulePtr = LoadLibrary(dynamicModulePath.c_str());
#elif LINUX
            m_DynamicModulePtr = dlopen(dynamicModulePath.c_str(), RTLD_NOW | RTLD_GLOBAL);
#endif // WINDOWS

            if (m_DynamicModulePtr != NULL)
            {
                m_DynamicModuleState = DynamicModuleState::DMS_Loaded;
                return true;
            }
            else
            {
#ifdef WINDOWS
                int errorCode = GetLastError();
#endif
                GetInternalErrorMessge(errorCode);
                return false;
            }

        }

        return false;
    }

    void* DynamicModuleLoader::GetFunction(const std::string functionName)
    {
        if (m_DynamicModulePtr)
        {
            void* tempFunctionPtr = NULL;
#ifdef WINDOWS
            tempFunctionPtr = GetProcAddress(m_DynamicModulePtr, functionName.c_str());
#elif LINUX
            tempFunctionPtr = dlsym(m_DynamicModulePtr, functionName.c_str());
#endif // WINDOWS

            if (tempFunctionPtr != NULL)
            {
                return tempFunctionPtr;
            }
            else
            {
#ifdef WINDOWS
                int errorCode = GetLastError();
#endif
                GetInternalErrorMessge(errorCode);
            }
        }

        return NULL;
    }

    bool DynamicModuleLoader::UnloadDynamicModule()
    {
        if (m_DynamicModulePtr)
        {
#ifdef WINDOWS
            if (FreeLibrary(m_DynamicModulePtr) == 0)
            {
                int errorCode = GetLastError(); // 得到错误代码
                GetInternalErrorMessge(errorCode);
                return false;
            }
#elif LINUX
            dlclose(m_DynamicModulePtr);
#endif
            m_DynamicModuleState = DynamicModuleState::DMS_UnLoaded;
            return true;
        }
        return false;
    }

#ifdef WINDOWS

#endif


    void DynamicModuleLoader::GetInternalErrorMessge(int errorCode)
    {
        std::string errorMessge = "";
#ifdef WINDOWS
        LPVOID lpMsgBuf;
        if (FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS |
            FORMAT_MESSAGE_MAX_WIDTH_MASK,
            NULL,
            errorCode,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR)&lpMsgBuf,
            0,
            NULL
        ))
        {
            errorMessge = (LPCTSTR)(lpMsgBuf);
            LocalFree(lpMsgBuf);
        }
#elif LINUX
        errorMessge = dlerror();
#endif // WINDOWS

        m_ErrorMessage = errorMessge;
    }

    std::string DynamicModuleLoader::GetErrorMessage()
    {
        return m_ErrorMessage;
    }

    bool DynamicModuleLoader::GetDynamicModuleState()
    {
        return (bool)m_DynamicModuleState;
    }
}