最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++使用宏實現動態(tài)庫加載

 更新時間:2022年12月16日 14:08:57   作者:CodeOfCC  
開發(fā)的時候,有些項目不能靜態(tài)鏈接動態(tài)庫,需要程序運行時加載動態(tài)庫。本文將使用宏來實現動態(tài)庫的加載,感興趣的小伙伴可以跟隨小編一起了解一下

前言

開發(fā)的時候,有些項目不能靜態(tài)鏈接動態(tài)庫,需要程序運行時加載動態(tài)庫,這個時候根據不同平臺我們通常使用LoadLibrary或dlopen將動態(tài)庫加載到程序中,并且還需要定義函數指針然后在獲取函數地址,這一系列的操作其實時比較麻煩的,尤其是方法較多的情況,基本沒法這么做,這時候就需要將這一過程進行適當的簡化。讓動態(tài)加載在方法較多的情況下盡量減少工作量。

一、為什么使用宏

一般的動態(tài)庫加載流程

1、Windows加載

#include<Windows.h>
extern "C"
{
#include "libavformat/avformat.h"
}
//定義方法類型
typedef  AVFormatContext*(*delegate_avformat_alloc_context)(void);
//定義方法指針
delegate_avformat_alloc_context dl_avformat_alloc_context;
HMODULE _hLibrary = nullptr;
//加載動態(tài)庫
void ImportMethod()
{
    auto _hLibrary = LoadLibraryA("avformat-58.dll");
    if (!_hLibrary)
    {
        printf("error:load %s failed!\n", "avformat-58.dll");
        return;
    }
    dl_avformat_alloc_context=(delegate_avformat_alloc_context)GetProcAddress(_hLibrary, "avformat_alloc_context");
    if (!dl_avformat_alloc_context)                                                                        
    {                                                                                                
        printf("error:%s load %s method failed!\n","avformat-58.dll", "avformat_alloc_context");                                    
    }        
}
//卸載動態(tài)庫
void UnImport()
{
    if (_hLibrary) {
        FreeLibrary(_hLibrary);
        _hLibrary = nullptr;
    }
}
//使用方法
void UseMethod() {
    auto ic = dl_avformat_alloc_context();
}

2、Linux加載

#include <dlfcn.h>
extern "C"
{
#include "libavformat/avformat.h"
}
//定義方法類型
typedef  AVFormatContext*(*delegate_avformat_alloc_context)(void);
//定義方法指針
delegate_avformat_alloc_context dl_avformat_alloc_context;
void* _hLibrary = nullptr;
//加載動態(tài)庫
void ImportMethod()
{
    auto _hLibrary = dlopen("libavformat.so", RTLD_LAZY);
    if (!_hLibrary)
    {
        printf("error:load %s failed!\n", "libavformat.so");
        return;
    }
    dl_avformat_alloc_context=(delegate_avformat_alloc_context)dlsym(_hLibrary, "avformat_alloc_context");
    if (!dl_avformat_alloc_context)                                                                        
    {                                                                                                
        printf("error:%s load %s method failed!\n","libavformat.so", "avformat_alloc_context");                                    
    }        
}
//卸載動態(tài)庫
void UnImport()
{
    if (_hLibrary) {
        dlclose(_hLibrary);
        _hLibrary = nullptr;
    }
}
//使用方法
void UseMethod() {
    auto ic = dl_avformat_alloc_context();
}

3、宏加載

很明顯上述流程對于加載一個方法來說流程過于復雜,在遇到庫比較多以及方法比較多的情況下,這種方法是很影響開發(fā)效率的。但是如果我們對上述流程進行宏包裝,事情將會變得簡單很多。比如上述引入ffmpeg的avformat_alloc_context方法只需要兩行即可:

extern "C"
{
#include "libavformat/avformat.h"
}
//使用宏動態(tài)加載方法
DLL_IMPORT("libavformat.so", avformat_alloc_context);
#define avformat_alloc_context DLL_IMPORT_NAME(avformat_alloc_context)
//使用方法
void UseMethod() {
    //與原方法名稱一致,直接調用
    auto ic = avformat_alloc_context();
}

二、具體實現

我們通過宏包裝上述兩個流程即可,同時還需要結合c++11的decltype關鍵字。

DllImportUtils.h

//
// Created by xin on 2022/6/15.
//
#ifndef DLLIMPORTUTILS_H
#define DLLIMPORTUTILS_H
void* GetDllMethodPtr(const char*dll,const char*method);
#define DLL_IMPORT(dll,method) decltype (method)* dllImport_##method;                            \
namespace {                                                                                         \
    class A##method{                                                                             \
    public: A##method() {                                                                         \
        dllImport_##method = (decltype(dllImport_##method))GetDllMethodPtr(dll, #method);         \
    }                                                                                             \
    };                                                                                             \
    A##method a##method;                                                                         \
}                                                                                                 
#define DLL_IMPORT_NAME(name) dllImport_##name
#endif 

DllImportUtils.cpp

#include"DllImportUtils.h"
#include<map>
#include<string>
#include<stdio.h>
#ifdef _WIN32
#include<Windows.h>
#define ACLoadLibrary(name) LoadLibraryA(name)
#define ACGetProcAdress(dll,name) GetProcAddress((HMODULE)dll,name)
#else
#include <dlfcn.h>
#define ACLoadLibrary(name) dlopen(name,RTLD_LAZY)
#define ACGetProcAdress(dll,name) dlsym(dll,name)
#endif // _Win32
std::map<std::string, void*>* _dllMap = nullptr;
class DllMapDisposer {
public:
    ~DllMapDisposer() {
        if (_dllMap)
            delete _dllMap;
    }
};
static DllMapDisposer _disposer;
void* GetDllMethodPtr(const char* dll, const char* method)
{
    if (!_dllMap)
        _dllMap = new std::map<std::string, void*>;
    auto iter = _dllMap->find(dll);
    void* hm;
    if (iter == _dllMap->end())
    {
        hm = (void*)ACLoadLibrary(dll);
        if (hm)
        {
            (*_dllMap)[dll] = hm;
        }
        else
        {
            printf("warnning:load %s failed!\n", dll);
        }
    }
    else
    {
        hm = iter->second;
    }
    if (hm) {
        auto methodPtr = ACGetProcAdress(hm, method);
        if (!methodPtr)
        {
            printf("error:%s load %s method failed!\n", dll, method);
        }
        return methodPtr;
    }
    return nullptr;
}

三、如何使用

1、引用頭文件

引用需要導入方法的頭文件

extern "C"
{
//需要導入方法的頭文件
#include "libavformat/avformat.h"
}
#include"DllImportUtils.h"

2、添加導入宏

//參數為庫的名稱和需要導入的方法
DLL_IMPORT("libavformat.so", avformat_alloc_context);
#define avformat_alloc_context DLL_IMPORT_NAME(avformat_alloc_context)

3、直接調用

void UseMethod() {
    //與原方法名稱一致,直接調用
    auto ic = avformat_alloc_context();
}

注:當前版本不支持卸載庫,程序啟動時方法就會被立刻加載。支持跨平臺,Windows、Linux都可以使用

總結

以上就是今天要講的內容,本文講述的方法很大程度的減少了工作量,而且可以不需要改代碼原有邏輯和方法名稱,適合需要動態(tài)加載不同版本的庫或者依賴庫的glibc不相同時的場景使用。

到此這篇關于C++使用宏實現動態(tài)庫加載的文章就介紹到這了,更多相關C++動態(tài)庫加載內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C++?OpenCV實現之實現紅綠燈識別

    C++?OpenCV實現之實現紅綠燈識別

    本文以實現行車過程當中的紅綠燈識別為目標,核心的內容包括:OpenCV輪廓識別原理以及OpenCV紅綠燈識別的實現具體步驟,感興趣的可以了解一下
    2022-08-08
  • C++中四種對象生存期和作用域以及static的用法總結分析

    C++中四種對象生存期和作用域以及static的用法總結分析

    以下是對C++中四種對象生存期和作用域以及static的用法進行了詳細的介紹,需要的朋友可以過來參考下
    2013-09-09
  • C++ set的使用方法詳解

    C++ set的使用方法詳解

    這篇文章主要介紹了C++ set的使用方法詳解的相關資料,希望通過本文能幫助到大家,讓大家理解掌握set的使用方法,需要的朋友可以參考下
    2017-10-10
  • C語言實現掃雷小游戲

    C語言實現掃雷小游戲

    這篇文章主要為大家詳細介紹了C語言實現掃雷小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • c++使用regex報錯regex_error兩種解決方案

    c++使用regex報錯regex_error兩種解決方案

    C++正則表達式是一個非常強大和實用的工具,但是使用它們時需要注意仔細檢查代碼是否符合語法規(guī)則,這篇文章主要給大家介紹了關于c++使用regex報錯regex_error的兩種解決方案,需要的朋友可以參考下
    2024-03-03
  • c語言中形參與實參的關系解讀

    c語言中形參與實參的關系解讀

    這篇文章主要介紹了c語言中形參與實參的關系,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • C++實現學生信息管理系統(tǒng)(完整版)

    C++實現學生信息管理系統(tǒng)(完整版)

    這篇文章主要為大家詳細介紹了C++實現學生信息管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 淺析string類字符串和C風格字符串之間的區(qū)別

    淺析string類字符串和C風格字符串之間的區(qū)別

    string類是標準庫的類,并不是內置類型,標準庫就像是我們自己定義的類差不多的,string類型對象沒有標配'\0'結尾的
    2013-09-09
  • C語言 指針與數組的詳解及區(qū)別

    C語言 指針與數組的詳解及區(qū)別

    這篇文章主要介紹了C語言 指針與數組的詳解及對比的相關資料,需要的朋友可以參考下
    2017-03-03
  • C語言遞歸實現字符串逆序的方式詳解

    C語言遞歸實現字符串逆序的方式詳解

    這篇文章主要介紹了C語言遞歸實現字符串逆序的方式詳解,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10

最新評論

韶山市| 阿拉善右旗| 左云县| 金堂县| 泽库县| 西盟| 青铜峡市| 福州市| 滨海县| 重庆市| 鄂温| 神木县| 房山区| 雷山县| 大港区| 沧州市| 德阳市| 临海市| 五家渠市| 南充市| 米林县| 错那县| 札达县| 巩义市| 武平县| 渭南市| 固原市| 成都市| 珲春市| 桃园市| 马鞍山市| 陆良县| 东平县| 黎川县| 西畴县| 岑溪市| 鸡西市| 团风县| 抚远县| 大余县| 防城港市|