欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

前言

開發(fā)的時候,有些項(xiàng)目不能靜態(tài)鏈接動態(tài)庫,需要程序運(yùn)行時加載動態(tài)庫,這個時候根據(jù)不同平臺我們通常使用LoadLibrary或dlopen將動態(tài)庫加載到程序中,并且還需要定義函數(shù)指針然后在獲取函數(shù)地址,這一系列的操作其實(shí)時比較麻煩的,尤其是方法較多的情況,基本沒法這么做,這時候就需要將這一過程進(jìn)行適當(dāng)?shù)暮喕W寗討B(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ù)雜,在遇到庫比較多以及方法比較多的情況下,這種方法是很影響開發(fā)效率的。但是如果我們對上述流程進(jìn)行宏包裝,事情將會變得簡單很多。比如上述引入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() {
    //與原方法名稱一致,直接調(diào)用
    auto ic = avformat_alloc_context();
}

二、具體實(shí)現(xiàn)

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

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、引用頭文件

引用需要導(dǎo)入方法的頭文件

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

2、添加導(dǎo)入宏

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

3、直接調(diào)用

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

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

總結(jié)

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

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

相關(guān)文章

  • 詳解C++內(nèi)存的代碼區(qū),全局區(qū),棧區(qū)和堆區(qū)

    詳解C++內(nèi)存的代碼區(qū),全局區(qū),棧區(qū)和堆區(qū)

    這篇文章主要為大家介紹了C++內(nèi)存的代碼區(qū),全局區(qū),棧區(qū)和堆區(qū),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • C++11中R字符串的作用小結(jié)

    C++11中R字符串的作用小結(jié)

    這篇文章主要介紹了C++11中R字符串的作用小結(jié),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-07-07
  • C++使用模板實(shí)現(xiàn)單鏈表

    C++使用模板實(shí)現(xiàn)單鏈表

    這篇文章主要為大家詳細(xì)介紹了C++使用模板實(shí)現(xiàn)單鏈表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • C語言可變參數(shù)函數(shù)詳解示例

    C語言可變參數(shù)函數(shù)詳解示例

    一般我們編程的時候,函數(shù)中形式參數(shù)的數(shù)目通常是確定的,在調(diào)用時要依次給出與形式參數(shù)對應(yīng)的實(shí)際參數(shù)。但在某些情況下我們希望函數(shù)的參數(shù)個數(shù)可以根據(jù)需要確定,因此c語言引入可變參數(shù)函數(shù)。典型的可變參數(shù)函數(shù)的例子有printf()、scanf()等,下面我就開始講解
    2013-11-11
  • C++11/14 線程調(diào)用類對象和線程傳參的方法

    C++11/14 線程調(diào)用類對象和線程傳參的方法

    這篇文章主要介紹了C++11/14 線程調(diào)用類對象和線程傳參的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • 黑客帝國數(shù)字雨效果VC6源代碼分享

    黑客帝國數(shù)字雨效果VC6源代碼分享

    這篇文章主要介紹了黑客帝國數(shù)字雨效果VC6源代碼分享,本文直接給出實(shí)現(xiàn)代碼,Win7下編譯通過,效果很酷,需要的朋友可以參考下
    2015-02-02
  • C++如何實(shí)現(xiàn)DNS域名解析

    C++如何實(shí)現(xiàn)DNS域名解析

    這片文章介紹了C++如何實(shí)現(xiàn)DNS域名解析,還有對相關(guān)技術(shù)的介紹,代碼很詳細(xì),需要的朋友可以參考下
    2015-07-07
  • C++結(jié)構(gòu)體中變長數(shù)組的使用問題分解刨析

    C++結(jié)構(gòu)體中變長數(shù)組的使用問題分解刨析

    變長數(shù)組在C++中指的是集合(也叫容器)如vector就是C語言中,所有的數(shù)組都不定長,沒有下標(biāo)越界的概念,數(shù)組實(shí)質(zhì)就是一個指針(由數(shù)組名充當(dāng))因此C語言中數(shù)組的長度沒有任何意義平常在C語言中講的不定長數(shù)組,其實(shí)就是指針
    2022-08-08
  • C++中volatile和mutable關(guān)鍵字用法詳解

    C++中volatile和mutable關(guān)鍵字用法詳解

    這篇文章主要介紹了C++中volatile和mutable關(guān)鍵字用法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • C語言實(shí)現(xiàn)簡單版三子棋

    C語言實(shí)現(xiàn)簡單版三子棋

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)簡單版三子棋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10

最新評論