广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++使用宏实现动态库加载
  • 901
分享到

C++使用宏实现动态库加载

摘要

目录前言一、为什么使用宏1、windows加载2、linux加载3、宏加载二、具体实现三、如何使用1、引用头文件2、添加导入宏3、直接调用总结前言 开发的时候,有些项目不能静态链接动

前言

开发的时候,有些项目不能静态链接动态库,需要程序运行时加载动态库,这个时候根据不同平台我们通常使用LoadLibrary或dlopen将动态库加载到程序中,并且还需要定义函数指针然后在获取函数地址,这一系列的操作其实时比较麻烦的,尤其是方法较多的情况,基本没法这么做,这时候就需要将这一过程进行适当的简化。让动态加载在方法较多的情况下尽量减少工作量。

一、为什么使用宏

一般的动态库加载流程

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;
//加载动态库
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");                                    
    }        
}
//卸载动态库
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;
//加载动态库
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");                                    
    }        
}
//卸载动态库
void UnImport()
{
    if (_hLibrary) {
        dlclose(_hLibrary);
        _hLibrary = nullptr;
    }
}
//使用方法
void UseMethod() {
    auto ic = dl_avformat_alloc_context();
}

3、宏加载

很明显上述流程对于加载一个方法来说流程过于复杂,在遇到库比较多以及方法比较多的情况下,这种方法是很影响开发效率的。但是如果我们对上述流程进行宏包装,事情将会变得简单很多。比如上述引入FFmpeg的avformat_alloc_context方法只需要两行即可:

extern "C"
{
#include "libavformat/avformat.h"
}
//使用宏动态加载方法
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都可以使用

总结

以上就是今天要讲的内容,本文讲述的方法很大程度的减少了工作量,而且可以不需要改代码原有逻辑和方法名称,适合需要动态加载不同版本的库或者依赖库的glibc不相同时的场景使用。

到此这篇关于C++使用宏实现动态库加载的文章就介绍到这了,更多相关C++动态库加载内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++使用宏实现动态库加载

本文链接: https://www.lsjlt.com/news/175077.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++使用宏实现动态库加载
    目录前言一、为什么使用宏1、Windows加载2、Linux加载3、宏加载二、具体实现三、如何使用1、引用头文件2、添加导入宏3、直接调用总结前言 开发的时候,有些项目不能静态链接动...
    99+
    2022-12-16
    C++ 宏 动态库加载 C++动态库加载 C++动态库 C++ 宏 动态库
  • C#中怎么加载动态库
    这期内容当中小编将会给大家带来有关C#中怎么加载动态库,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。C#语言有很多值得学习的地方,这里我们主要介绍C#实现加载动态库,包括介绍将 C 或 C++ 函数封装成...
    99+
    2023-06-17
  • Golang使用CGO与Plugin技术运行加载C动态库
    目录文章简介技术背景解决方案1解决方案2文章简介 本文介绍一种 Golang 程序在运行时加载 C 动态库的技术,跳过了 Golang 项目编译阶段需要链接 C 动态库的过程,提高了...
    99+
    2022-11-13
  • 利用Java如何实现动态加载数据库驱动
    利用Java如何实现动态加载数据库驱动?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。代码实现在此只例出核心代码,就是动态加载数据库驱动的类,只是此处暂时没有考虑到数据库连接池的...
    99+
    2023-05-31
    java 动态加载 驱动
  • java实现动态编译并动态加载
    在D盘test目录下有个java文件:AlTest.java public class AlTest { public String sayHello(){ System...
    99+
    2022-11-12
  • c++动态库调用的实现
    目录一、生成dll二、调用dll在平时的开发中某些情况,动态库和静态库是程序开发的不二法门,例如封装一个库,供别人调用(日志库、字符串处理库、设备信息采集库等),比如接入第三方系统或...
    99+
    2022-11-13
  • 如何浅析C++动态加载DLL在Windows Mobile下实现
    如何浅析C++动态加载DLL在Windows Mobile下实现,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。静态加载DLL的方法使用Native C++的开发...
    99+
    2023-06-17
  • springboot动态加载类怎么实现
    要实现Spring Boot动态加载类,可以使用以下步骤: 创建一个ClassLoader对象,用于动态加载类。可以使用URLC...
    99+
    2023-10-25
    springboot
  • 如何使用SpringSecurity实现动态加载权限信息
    这篇文章主要介绍了如何使用SpringSecurity实现动态加载权限信息,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。①数据库中资源与角色对应关系,以及角色和用户对应关系如...
    99+
    2023-06-22
  • java实现动态编译并动态加载的方法
    小编给大家分享一下java实现动态编译并动态加载的方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在D盘test目录下有个java文件:AlTest.javap...
    99+
    2023-06-14
  • el-menu动态加载路由的实现
    先看需要实现的效果 这里有一级也有二级菜单,注意二级菜单的父目录(”选项设置“点击不会跳转,只是展开目录),然后点击去详情页,需要跳到一个隐藏的路由,不在菜...
    99+
    2023-05-15
    el-menu动态加载路由 el-menu动态路由
  • Angular.js怎么实现动态加载组件
    小编给大家分享一下Angular.js怎么实现动态加载组件,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言有时候需要根据URL...
    99+
    2022-10-19
  • JavaScript实现动态加载删除表格
    本文实例为大家分享了JavaScript实现动态加载删除表格的具体代码,供大家参考,具体内容如下 代码: <!DOCTYPE html> <html lang...
    99+
    2022-11-12
  • Ajax如何实现动态加载数据
    这篇文章给大家分享的是有关Ajax如何实现动态加载数据的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。这个随笔实现了一个Ajax动态加载的例子。使用.net 的MVC框架实现。这个例子重点在前后台交互,其它略写。开...
    99+
    2023-06-08
  • VUE路由动态加载如何实现
    这篇文章主要讲解了“VUE路由动态加载如何实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“VUE路由动态加载如何实现”吧!首先新建vue工程,一般我们不会特殊处理路由,但当项目页面越来越多...
    99+
    2023-07-04
  • C#中如何使用反射和动态加载程序集
    C#中如何使用反射和动态加载程序集引言:在C#中,反射(Reflection)是一种强大的机制,它允许我们在运行时获取和操作程序的元数据,包括类型信息、成员信息等。而动态加载程序集则是通过反射来实现的一种常见应用,并且在一些特定场景中非常有...
    99+
    2023-10-22
    C# 反射 动态加载
  • 使用Ajax怎么实现一个动态加载组合框
    这篇文章将为大家详细讲解有关使用Ajax怎么实现一个动态加载组合框,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一  province.jsp<%@ page&nb...
    99+
    2023-06-08
  • SpringBoot使用Shiro实现动态加载权限详解流程
    目录一、序章二、SpringBoot集成Shiro1、引入相关maven依赖2、自定义Realm3、Shiro配置类三、shiro动态加载权限处理方法四、shiro中自定义角色与权限...
    99+
    2022-11-13
  • Android应用开发中Fragment的静态加载与动态加载实例
    1、Fragment的静态使用 Fragment是作为Activity的UI的一部分,它内嵌在Activity中,多个Fragment可以把一个Activity分成多个部分,这...
    99+
    2022-06-06
    静态 fragment 动态 Android
  • Android 中动态加载.jar的实现步骤
    首先第一个是 jar 文件的制作,Java 里面直接把 .class 文件打包到 .jar 文件里面就可以了,但是 Android 的 Dalvik VM 是不认 Java 的...
    99+
    2022-06-06
    jar 动态 Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作