精华内容
下载资源
问答
  • qlibrary
    千次阅读
    2020-12-29 10:37:17
    #include <QLibrary>
    
    int a=1,b=2,c=6;
    typedef void (*myfun)(int,int,int *); // 定义导出函数类型
    
    QLibrary hdll( "test01.dll" ); //加载dll,当前目录
    if(hdll.load())
    {
    	myfun fun1 = (myfun)hdll.resolve("MYSUB"); //用resolve来解析fun1函数
    	if ( fun1 ) //解析成功则进行运算并提示相关信息
    	{
    		fun1(a,b,&c);
    		QString qss=tr("dll加载成功!\n 1+2=")+QString::number(c,10);
    	}
    }

     QT 源码之 QLibrary 。

    1、win下动态库调用有关的函数包括:

    (1)LoadLibrary,装载动态库。

    (2)GetProcAddress,猎取要引入的函数,将符号名或标识号转换为DLL内部地址。

    (3)FreeLibrary,释放动态链接库。

    2、unix上与动态库调用有关的函数包括:

    (1)_打开动态链接库:dlopen,函数原型void *dlopen (const char *filename, int flag);

    dlopen用于打开指命名字(filename)的动态链接库,并前往操作句柄。

    (2)取函数执行地址:dlsym,函数原型为: void *dlsym(void *handle, char *symbol);

    dlsym根据动态链接库操作句柄(handle)与符号(symbol),前往符号对应的函数的执行代码地址。

    (3)关闭动态链接库:dlclose,函数原型为: int dlclose (void *handle);

    dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的运用计数为0时,才会真正被系统卸载。

    (4)动态库毛病函数:dlerror,函数原型为: const char *dlerror(void); 当动态链接库操作函数执行失利时,dlerror能够前往犯错信息,前往值为NULL时表示操作函数执行成功

    下面是我用vc编写的一个动态库中的函数add:

    extern "C" __declspec(dllexport) int __stdcall add(int a,int b)  
    {  
        return a+b;  

    下面我就用QLibrary来调用一下:

    QLibrary lib("QtDllTest.dll");  
    if (lib.load())  
    {  
        typedef int(*AddFunction)(int a,int b);  
        AddFunction Add=(AddFunction)lib.resolve("add");  
        if (!Add)  
        {  
            cout<<"failed"<<endl;  
        }  
        else  
        {  
           int m;  
           m=Add(1,1); //来个计算1+1  
           cout<<"result:"<<m<<endl;  
        }  
        lib.unload();  
    }  
    else  
    {  
        cout<<"failed"<<endl;  

    首先将目录切换到QTDIR\src\corelib\plugin,这里面就是QLibrary实现的源代码,打开qlibrary_p.h(熟悉了Qt的经常运用手法,就知道,这就是QLibrary内部实现的代码),能够看到

    bool load_sys();  
    bool unload_sys();  
    void *resolve_sys(const char *); 
    三个函数。在qlibrary.cpp中能够找到调用这三个函数的地方

    bool QLibrary::load ()调用了load_sys;  
    bool QLibrary::unload ()调用了unload_sys;  
    void * QLibrary::resolve ( const char * symbol )调用了resolve_sys 
    然则并没有找到这三个函数的实现,这是这么回事呢?

    打开QTDIR\src\corelib\plugin\plugin.pri资料,

    win32 {  
     SOURCES += plugin/qlibrary_win.cpp  
    }  
    unix {  
     SOURCES += plugin/qlibrary_unix.cpp  

    原来如此啊。

    咱们仔细看下qlibrary_win.cpp资料,load_sys函数调用了LoadLibrary,unload_sys调用了FreeLibrary,resolve_sys调用了GetProcAddress。

    而在qlibrary_unix.cpp资料中,各种linux平台又分好多种。然则基本上load_sys调用了dlopen,unload_sys调用了dlclose,resolve_sys调用了dlsym。

    在HPUX中dlopen对应shl_load,dlclose对应shl_unload,dlsym对应shl_findsym。

     

     

    更多相关内容
  • QLibrary_QLibrary_

    2021-09-29 15:57:36
    Qlibrary的基础使用,属于新人练习调用
  • Qt-QLibrary

    千次阅读 2020-01-01 13:42:13
    在写本文之前,先发几句感慨吧,2019年过的...文章目录QLibrary ClassPublic TypesProPertiesPublicFunctions QLibrary Class QLibrary 类是一个在运行时可以加载动态链接库的类 Header: #include qmake:QT += co...

    在写本文之前,先发几句感慨吧,2019年过的很快,觉得自己今年是从观念到习惯上都发生比较大改变的人,但是离自己的想象中的样子差的还挺远。

    QLibrary Class

    QLibrary 类是一个在运行时可以加载动态链接库的类
    Header: #include
    qmake:QT += core
    Inherits: QObject
    注意:本类中的所有的方法都是可以重载的

    Public Types

    enum LoadHint {
    	ResolveAllSymbolsHint,	//
    	ExportExternalSymbolsHint,
    	LoadArchiveMemberHint,
    	PreventUnloadHint,
    	DeepBindHint
    }
    

    ProPerties

    fileName:QString
    loadHints:LoadHints

    PublicFunctions

    QLibrary(QObject * parant = nullptr)
    QLibrary(const QString &fileName, QObject * parent = nullptr)
    QLibrary(const QString &fileName, int verNum, QObject * parent = nullptr)
    QLibrary(const QString &filename, const QString &version, QObject * parent = nullptr)
    virtual ~QLibrary()
    QString errorString() const
    QString fileName() const
    bool isLoaded() const
    bool load()
    QLibrary::LoadHits loadHints() const
    QFunctionPointer resolve(const char *symbol)
    void setFileName(const QString &fileName)
    void setFileNameAndVersion(const QString &fileName, int versionNumber)
    void setFileNameAndVersion(const QString &fileName, const QString &version)
    void setLoadHints(QLibrary::LoadHints hints)
    bool unload()
    

    Static Public Members

    bool isLibrary(const QString &fileName)
    QFunctionPointer resolve(const QString &fileName, const char* symbol)
    QFunctionPointer resolve(const QString &fileName, int verNum, const char* symbol)
    QFunctionPointer resolve(const QString &fileName, const QString &version, const char *symbol)
    const QMetaObject staticMetaObject
    

    Additional Inherited Members

    pass

    Detailed Description

    QLibrary类提供了在程序运行中的时候加载共享库的方法
    一个QLibrary的实例操作一个共享库的对象文件(我们称之为共享库,但是通常大家都叫“DLL”),QLibrary可以提供独立于平台方式来访问库中的函数,你可以在构造函数中仅仅传入一个文件名,或者显式的使用函数setFileName()来设定文件名,当加载共享库的时候,QLibrary或搜索系统指定的所有的库的位置(比如:Unix中的LD_LIBRARY_PATH路径)
    如果文件名是一个绝对路径,则应用程序会直接搜索这个路径,如果文件找不到,QLibrary会尝试搜索不同文件名的后缀,比如Unix和Max中的“lib”文件等等
    如果不是一个绝对路径,系统将修改搜索顺序为,先找系统指定的目录,然后再找文件指定的
    这样就确保了共享库只需要通过其文件名就可以确定其身份,这样的话,相同的代码将会在不同的操作系统中使用,直到在库中找到相关的文件
    最重要的函数是load(),我们用它来动态的加载动态库文件,函数isLoaded()是用来检查是否加载顺利的完成了,函数resolve()是用来解析库中的符号,如果库在前面没有加载的话,resolve()函数将会隐式的加载这个动态库,一旦加载成功,动态库将在程序终止之前存在程序的内存中,你也可以手动的使用函数unload()来将动态库卸载,但是如果此时有其他的Qlibrary在使用这个动态库的时候,将不能被卸载,只有当每一个实例都调用unload()函数后,此动态库才会被卸载
    典型的使用QLibrary的方法是解析共享库中的接口函数,然后调用这个符号所代表的的C函数,这叫显式链接,与其相对应的是隐式链接,隐式链接在程序编译过程中就链接好了
    下面的代码片段将会加载一个共享库,并解析符号“mysymbol”,一旦这些事情成功完成后,将会调用这个函数,如果不成功的话,比如共享库文件不存在,或者符号没有定义,函数指针将会返回0

    QLibrary myLib("mylib");
    typedef void (*MyPrototype) ();
    MyPrototype myFunction = (MyPrototype) myLib.resolve("mysymbol");
    if (myFunction)
    	myFunction();
    

    这个符号必须是作为C函数来导出的,这样的话,resolve()函数才能工作,这意味着如果共享库是有C++编译器来编译的,必须加上 extern “C” ,在windows平台中还需要添加dllexxport的宏指令,详细的请看函数resolve()的介绍,为了操作方便,这里还有一个静态函数resolve(),你可以在不显示的声明加载库的情况下来使用共享库中的函数

    typedef void (*MyPrototype) ();
    MyPrototype myFunction = 
    	(MyPrototype) QLibrary::resolve("mylib", "mysymbol");
    if (myFunction)
    	myFunction();
    

    更多的内容请看类 QPluginLoader

    Member Type Documentation

    enum QLibrary::LoadHint
    flags QLibrary::LoadHints

    这些枚举变量描述动态库加载的时候的可以用来改变使用库的方法的暗示,这些值代表着当库在加载的时候符号是怎么被解析的,你也可以指定使用函数setLoadHints()来指定

    枚举变量描述
    QLibrary::ResolveAllSymbolsHint0x01当库加载的时候,库中的所有的符号都被加载,而不是当函数resolve()调用的时候才加载
    QLibrary::ExportExternalSymbolsHint0x02导出库中未解析的和外部符号,以便可以在以后加载的其他动态加载的库中解析它们。
    QLibrary::LoadArchiveMemberHint0x04允许库的文件名在存档文件中指定特定的目标文件。如果给出此提示,则库的文件名由一个路径组成,该路径是对存档文件的引用,然后是对存档成员的引用。
    QLibrary::PreventUnloadHint0x08防止在调用close()时从地址空间卸载库。如果稍后调用open(),则不会重新初始化库的静态变量。
    QLibrary::DeepBindHint0x10指示链接程序在解析加载库中的外部符号时,选择加载库中的定义而不是加载应用程序中的导出定义。此选项仅在Linux上受支持。

    Property Documentation

    fileName: QString
    这个属性代表库的文件名
    我们建议省略文件名的后缀,因为QLibrary会自己添加
    当加载动态库的时候,QLibrary将会在系统指定的目录中全部寻找,除非路径名是使用的绝对路径,函数fileName()将返回动态库的文件名的完全路径

    • 访问方式
      QString fileName() const
      void setFileName(const QString &fileName)

    loadHints: LoadHints
    给出函数load(),指定此类的表现
    你可以给出一些关于如何解析符号的暗示,通常来说,符号在库加载的时候是没有被解析的,而是通过调用函数resolve()来解析的,如果你设置了loadHints为ResolveAllSymbolsHint,这样的话,所有的符号都会在加载共享库的时候被解析出来,前提时你的平台支持这样做
    如果设置了LoadArchiveMemberHint,用不到省略
    注意的是,有的暗示是需要平台支持的,所以需要事先了解
    默认情况下,不会设置任何的flags,所以符号不会再加载的时候解析,
    注意,如果已经加载了,是无法设置这个属性的,而且这个属性是在所有的实例中共享的

    • 访问方法:
      QLibrary::LoadHints loadHints() const
      void setLoadHints(QLibrary::LoadHints hints)

    关于成员函数

    QLibrary::QLibrary(QObject *parent = nullptr)

    构造函数

    QLibrary::QLibrary(const QString &fileName, QObject *parent = nullptr)

    使用带共享库名的构造函数
    我们不建议使用带后缀的文件名,因为系统会自己看情况添加

    QLibrary::QLibrary(const QString &fileName, int verNum, QObject *parent = nullptr)

    使用带文件名和版本号的构造函数,不过通常来讲,版本号在windows平台中会忽略

    QLibrary::QLibrary(const QString &fileName, const QString &version, QObject *parent = nullptr)

    使用带文件名和版本号的构造函数,不过通常来讲,版本号在windows平台中会忽略

    [virtual] QLibrary::~QLibrary()

    析构函数
    除非显式的调用了unload()函数,否则动态库将会在程序终止前一直存在于内存中

    QString QLibrary::errorString() const

    返回类中的最后一次故障的字符串,在目前位置,故障只有在函数laod(),unload(),或者resolve()调用的时候才会出现

    [static] bool QLibrary::isLibrary(const QString &fileName)

    返回这个文件是不是一个动态库

    bool QLibrary::isLoaded() const

    如果库被成功加载将返回真

    bool QLibrary::load()

    加载成功将返回真,否则返回假

    QFunctionPointer QLibrary::resolve(const char *symbol)

    返回指定符号的函数指针,在这之前动态库需要加载成功,否则这个函数将返回nullptr,下面是一个例子

    typedef int (*AvgFunction) (int, int);
    AvgFunction avg = (AvgFuntion) library->resolve("avg");
    if (avg)
    	return avg(5, 8);
    else
    	return -1;
    

    符号必须以C函数的形式来导出,举个例子

    extern "C" MY_EXPORT int avg(int a, int b)
    {
    	return (a + b) / 2
    }
    

    然后 MY_EXPORT 中需要如下定义

    #ifdef Q_OS_WIN
    #define MY_EXPORT __declspec(dllexport)
    #else
    #define MY_EXPORT
    #endif
    

    [static] QFunctionPointer QLibrary::resolve(const QString &fileName, const char *symbol)

    这是一个重载函数
    通过加载库的文件名,然后返回导出的符号的地址,需要注意的是,文件名不需要指定平台指定的后缀名,动态库将会在应用程序应用程序存在的时候保持加载

    [static] QFunctionPointer QLibrary::resolve(const QString &fileName, int ver Num, const char *symbol)

    这是一个重载函数
    和上面的函数类似

    [static] QFunctionPointer QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)

    和上面的函数类似

    void QLibrary::setFileNameAndVersion(const QString &fileName, int versionNumber)

    分别设置文件名和文件版本

    void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &version)

    分别设置文件名和文件版本

    bool QLibrary::unload()

    成功卸载库则返回真,否则返回假
    在应用程序终止的时候将自动执行这个函数,多以你不需要自己去调用这个函数

    展开全文
  • Qt插件:QLibrary

    千次阅读 2021-09-08 13:27:25
    QLibrary 对象的实例对单个共享对象文件(库文件)进行操作。QLibrary 以独立于平台的方式提供对库中功能的访问。可以在构造函数中传递文件名,也可以使用 setFileName() 显式设置它。加载库时,除非文件名具有绝对...

    一、描述

    QLibrary 对象的实例对单个共享对象文件(库文件)进行操作。QLibrary 以独立于平台的方式提供对库中功能的访问。可以在构造函数中传递文件名,也可以使用 setFileName() 显式设置它。加载库时,除非文件名具有绝对路径,否则QLibrary 将搜索所有系统特定的库位置(例如 Unix 上的 LD_LIBRARY_PATH)。

    如果文件名是绝对路径,则首先尝试加载此路径。如果找不到文件,QLibrary 会尝试使用不同平台特定的文件前缀(如 Unix 和 Mac 上的“lib”)和后缀(如 Unix 上的“.so”、Mac 上的“.dylib”或“.dylib”、在 Windows 上的“.dll”)。

    如果文件名不是绝对路径,那么 QLibrary 会修改搜索顺序以首先尝试系统特定的前缀和后缀,然后是指定的文件路径。这使得指定仅由其基本名称(即没有后缀)标识的共享库成为可能,因此相同的代码可以在不同的操作系统上运行,但仍然可以最大限度地减少尝试查找库的次数。

    因为 QLibrary 会自动查找具有适当后缀的文件,所以建议在文件名中省略文件的后缀。

    QLibrary 的多个实例可用于访问同一个物理库。加载后,库将保留在内存中,直到应用程序终止。

    解析库中的导出符号

    QLibrary 的典型用途是解析库中的导出符号,并调用该符号表示的 C 函数。这被称为“显式链接”,与“隐式链接”相反,当将可执行文件链接到库时,这是由构建过程中的链接步骤完成的。

    以下代码片段加载一个库,解析符号“mysymbol”,并在成功时调用该函数。如果出现问题,例如库文件不存在或符号未定义,函数指针将为 nullptr 且不会被调用。

    QLibrary myLib("mylib");
    typedef void (*MyPrototype)();
    MyPrototype myFunction = (MyPrototype) myLib.resolve("mysymbol");
    if (myFunction)
        myFunction();

    符号必须从库中导出为 C 函数,resolve() 才能工作。 这意味着如果库是使用 C++ 编译器编译的,则该函数必须包含在 extern "C" 块中。 在 Windows 上,这也需要使用 dllexport 宏。 为方便起见,如果只想调用库中的函数而不先显式加载库,则可以使用静态 resolve() 函数:

    typedef void (*MyPrototype)();
    MyPrototype myFunction = (MyPrototype) QLibrary::resolve("mylib", "mysymbol");
    if (myFunction)
        myFunction();

    二、类型成员

    1、enum QLibrary::LoadHint:此枚举描述了可用于更改库加载(load())时处理方式的可能标志。这些值指示加载库时如何解析符号。默认情况下,这些标志都没有设置,并且不会导出外部符号以在其他动态加载的库中解析。在库加载后设置标志无效,并且 loadHints() 不会反映标志更改。

    • ResolveAllSymbolsHint:库中的所有符号在加载时被解析,而不仅仅是在调用 resolve() 时。
    • ExportExternalSymbolsHint:导出库中未解析的和外部符号,以便它们可以在稍后加载的其他动态加载的库中解析。
    • LoadArchiveMemberHint:库的文件名指定存档文件中的特定目标文件。如果设置此标志,则文件名由两个部分组成:路径是对存档文件的引用,后跟是对存档成员的引用的第二个部分。例如,文件名 libGL.a(shr_64.o) 将引用名为 libGL.a 的存档文件中的库 shr_64.o。 这仅在 AIX 平台上受支持。
    • PreventUnloadHint:阻止库从地址空间通过close()卸载。如果之后再有open()调用,库中的静态变量不会重新初始化。
    • DeepBindHint:链接器在解析加载库中的外部符号时优先选择加载库中的定义而不是加载应用程序中的导出定义。此选项仅在 Linux 上受支持。

    三、成员函数

    1、QLibrary(const QString &fileName, const QString &version, QObject *parent = nullptr)

    将加载由 fileName 和完整版本号 version 指定的库。版本号在 Windows 上被忽略。

    2、QLibrary(const QString &fileName, int verNum, QObject *parent = nullptr)

    将加载由 fileName 和主要版本号 verNum 指定的库。版本号在 Windows 上被忽略。

    3、QLibrary(const QString &fileName, QObject *parent = nullptr)

    将加载由 fileName 指定的库。

    4、~QLibrary()

    销毁 QLibrary 对象。除非显式调用 unload(),否则库将保留在内存中,直到应用程序终止。

    5、QString errorString()

    返回一个文本字符串,其中包含对发生的最后一个错误的描述。当前,仅当 load()、unload() 或 resolve() 由于某种原因失败时才会设置 errorString。 

    6、【静态】bool isLibrary(const QString &fileName)

    fileName 是否具有可加载库的有效后缀。

    • Windows:*.dll、*.DLL
    • Unix/Linux:*.so
    • AIX:*.a
    • HP-UX:*.sl、 *.so (HP-UXi)
    • macOS、iOS:*.dylib、*.bundle、*.so

    Unix 上的尾随版本号将被忽略。

    7、bool isLoaded() 

    库是否已加载。

    8、bool load()

    加载库,如果库加载成功则返回true;否则返回false。由于 resolve() 总是在解析任何符号之前调用此函数,因此没有必要显式调用它。

    9、QFunctionPointer resolve(const char *symbol)

    【静态】QFunctionPointer resolve(const QString &fileName, const char *symbol)

    【静态】QFunctionPointer resolve(const QString &fileName, int verNum, const char *symbol)

    【静态】QFunctionPointer resolve(const QString &fileName, const QString &version, const char *symbol)

    返回导出的符号符号的地址。如有必要,将加载库。 如果无法解析符号或无法加载库,则该函数返回 nullptr。

    QFunctionPointer 是 void (*)() 的 typedef,指向不带参数并返回 void 的函数的指针。

    例:

    添加一个库工程。内容如下:

    testlibrary.h

    #ifndef TESTLIBRARY_H
    #define TESTLIBRARY_H
    
    extern "C" __declspec(dllexport) int sum(int a, int b);
    
    #endif

    testlibrary.cpp(必须有cpp文件)

    #include "testlibrary.h"
    
    int sum(int a, int b)
    {
        return a+b;
    }

    创建一个工程导出整个库中的函数:

    using Fun = int (*)(int, int);
    
    int main(int argc, char *argv[])
    {
        QLibrary lib("testLibrary");
    //  Fun fun = reinterpret_cast<Fun>(QLibrary::resolve("testLibrary","sum"));
        Fun fun = reinterpret_cast<Fun>(lib.resolve("sum"));
        if (fun)
        {
            qDebug()<<fun(100,200);
        }
        else
        {
            qDebug()<<lib.errorString();
        }
    }

    知识点:类型转换 函数指针

    10、void setFileNameAndVersion(const QString &fileName, int versionNumber)

    将 fileName 属性和主要版本号分别设置为 fileName 和 versionNumber。在 Windows 上忽略 versionNumber。

    void setFileNameAndVersion(const QString &fileName, const QString &version)

    将 fileName 属性和完整版本号分别设置为 fileName 和 version。在 Windows 上忽略version 。

    11、bool unload()

    如果可以卸载库,则卸载库并返回 true;否则返回false。

    这在应用程序终止时自动发生,因此通常不需要调用此函数。

    如果 QLibrary 的其他实例正在使用相同的库,则调用将失败,并且只有在每个实例都调用了 unload() 时才会发生卸载。

    注意,在 Mac OS X 10.3 (Panther) 上,无法卸载动态库。

    展开全文
  • QLibrary 加载动态库

    2021-05-16 10:41:15
    阅读本文大概需要 6.6分钟 一般情况下在没有头文件支持情况下,想要引入某个动态库,最好的办法就是使用「动态加载」的方法,在Qt中一般使用QLibyary来操作 常用 api QLibrary(const QString& fileName, QObject *...

    阅读本文大概需要 6.6分钟

    一般情况下在没有头文件支持情况下,想要引入某个动态库,最好的办法就是使用「动态加载」的方法,在Qt中一般使用QLibyary来操作

    常用 api

    QLibrary(const QString& fileName, QObject *parent = nullptr);

    QFunctionPointer resolve(const char *symbol);

    bool load();

    bool unload();

    bool isLoaded() const;

    下面我们来看下详细的使用过程

    创建动态库

    我们创建一个「子工程」,用来编写我们的测试方法,该工程需要导出为动态库,完整的示例如下所示

    ├─App

    │ App.pro

    │ main.cpp

    └─Libs

    Libs.pro

    SDKCore.cpp

    SDKCore.h

    SDKCoreImpl.cpp

    SDKCoreImpl.h

    SDKCore_global.h

    SDKStruct.h

    我们创建一个函数,并且导出

    SDKCore.h

    extern "C" SDK_EXPORT int runFunction(const char * funName, const DS_Request &request, DS_Request& response);

    SDKCore.cpp

    int runFunction(const char *funName, const DS_Request &request, DS_Request &response)

    {

    Internal::SDKCoreImpl m_pCoreImpl;

    int nRet = -1;

    QMetaObject::invokeMethod(&m_pCoreImpl, funName,

    Qt::DirectConnection,

    Q_RETURN_ARG(int, nRet),

    Q_ARG(DS_Request, request),

    Q_ARG(DS_Request&,response));

    return nRet;

    }

    这里为了访问方便,具体的函数都放在了SDKCoreImpl中实现,调用采用了反射,调用的时候直接传方法字符串即可

    上面中入参和出参数据格式是自定义的,为了统一而自定义,具体如下所示

    struct DS_Request{

    QString m_strData;

    QByteArray m_baStream;

    };

    这样就兼容所有的格式了,不管是传 字符串还是数据流都使用统一的格式

    这里写一个简单的加法运算

    int SDKCoreImpl::addNum(const DS_Request &request, DS_Request &response)

    {

    QVariantMap map = QJsonDocument::fromJson(request.m_strData.toLatin1()).toVariant().toMap();

    int nValue1 = map.value("nValue1").toInt();

    int nValue2 = map.value("nValue2").toInt();

    int nResult = nValue1 + nValue2;

    QVariantMap mapResult;

    mapResult.insert("result", nResult);

    QJsonDocument doc = QJsonDocument::fromVariant(mapResult);

    response.m_strData = QString(doc.toJson());

    return SDKCODE_SUCCEED;

    }

    加载动态库

    加载动态库就变的很简单了,只需要几行代码即可获取到对应的函数符号

    QLibrary library(strSDKName);

    bool bLoad = library.load();

    只要动态库路径合法就会加载成功,一般加载失败可能就是路径后者导出符号有问题,遇到这些问题可以排查下

    使用前先定义一个函数指针

    typedef int (* pRunFunctionFun)(const char *, const DS_Request &, DS_Request&);

    调用addNum函数

    pRunFunctionFun pFun = (pRunFunctionFun) library.resolve("runFunction");

    if ( pFun)

    {

    int nRet = pFun("addNum", request, response);

    qDebug() << "add Resut:" << nRet << response.m_strData;

    }

    这样一个完整的调用流程就跑通了

    优化代码

    但是,如果你认为完了,那就错了,仔细看下就会发现上述代码有冗余,难道每调用不同的函数,都要重复上述过程么?肯定不会呀,程序员不会自己干重复的事情,要重复只能让机器去做

    下面优化下,把重复的代码单独封装下,定义成宏

    通过上述代码,我们可以看出来,首先这个方法可以封装成模板,每一次调用都是一样的

    library.resolve("")

    封装成模板调用

    template

    T getFunction(QLibrary *lib, const char *symbol)

    {

    T f = (T)lib->resolve(func);

    if (f == nullptr)

    {

    return nullptr;

    }

    return f;

    }

    然后接着优化,获取函数符号流程封装成宏

    #define GET_SDK_FUNC(type, func, symbol) GET_FUNC(sdk, type, func, symbol);

    #define GET_FUNC(sdk, type, func, symbol) \

    type func = getFunction(&sdk, symbol); \

    if (func == nullptr) \

    { \

    qDebug()<

    return 0; \

    }

    优化完成后,我们看下调用过程会如何更简单

    QLibrary library(strSDKName);

    bool bLoad = library.load();

    GET_FUNC(library, pRunFunctionFun, runFun, "runFunction");

    int nRet = runFun("addNum", request, response);

    完整代码已经上传到GitHub,感兴趣的可以自行去下载

    总结

    在平时工作中,很多大型工程都是动态库调用,这样做的好处就是方便他人直接调用使用现有功能和业务,减少重复复杂的工作,提高我们的工作效率

    上述代码中有没有发现一条迷惑之处,就是动态库的路径和名称没有看到呀,是怎么加载的?

    这个其实用到了之前介绍的一种技术,qmake语法糖

    阅读过源码你就会发现,我在pri文件中编写了字符串宏定义,这样在代码中就可以直接调用对应的字符串了,如果那一天要修改,那么只修改pri文件即可,其它都不需要动

    DEFINES += LIB_DIR_PATH=\"\\\"$$LIB_DIR_PATH\\\"\"

    DEFINES += FILE_DLL_EXT=\"\\\"$$FILE_DLL_EXT\\\"\"

    DEFINES += LIB_NAME=\"\\\"$$LIB_NAME\\\"\"

    展开全文
  • 目录 一、使用Qt编译C动态库 二、使用QLibrary调用共享库 一、使用Qt编译C动态库 使用Qt新建一个C项目 cbb_frame,在项目中我们声明和定义两个函数,并导出函数。在cbb_mylog中我们使用了函数指针,这里为啥这样干,...
  • #endif #include "mainwindow.h" #include "ui_mainwindow.h" #include "qlibrary.h" #include "qmessagebox.h" #include "string.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::...
  • QLibrary

    2018-10-30 15:30:17
    QLibrary lib(“QtDllTest.dll”); if (lib.load()) { typedef int(*AddFunction)(int a,int b); AddFunction Add=(AddFunction)lib.resolve(“add”); if (!Add) { cout&lt;&lt;“failed”&lt;&lt;...
  • QLibrary 加载失败

    2022-05-18 15:37:11
    QLibrary 加载失败 QLibrary 加载失败,输出显示加载对应dll后又卸载 看看对应的dll库的依赖库是否完全
  • QLibrary 出现错误的排查

    千次阅读 2021-03-09 09:42:29
    当使用QLibrary加载动态库的时候,会经常出现例如Load为空,或者resolve为空的情况,这时候排查问题所在可以通过QLibrary自己提供的一个函数errorString()获得错误信息,以便与处理问题的所在 是个比较好的排查方式 ...
  • QLibrary实现机制

    2021-05-19 10:19:31
    QLibrary加载动态库 QT加载动态库操作
  • 在开发中遇到了这样的问题,使用QLibrary加载动态库,每调用一次,句柄数就会增加,因为我的程序要频繁的调用动态库,最终导致程序崩溃。调用的代码如下:typedef long LPARAM;typedef unsigned int WPARAM;typedef ...
  • 使用QLibrary可以在程序运行时加载动态链接库。一个QLibrary的实例作用于一个单一的共享库上。QLibrary提供了一种平台无关的方式访问库中的函数。可以在构建QLibrary的实例时将要加载的库文件传入,也可以在创建实例...
  • 背景 项目中需要对操纵手柄进行读取,在网上找了几篇博客,基本都是依赖winmm.lib,但其中一篇直接加载它的动态库,从里面把...QLibrary mylib("Winmm.dll"); typedef int (*MyPrototype) (HWND, UINT, UINT, BOOL); M
  • QT的QLibrary类的使用

    千次阅读 2020-12-14 10:22:22
    QLibrary类在运行时加载共享库。 QLibrary对象的实例在单个共享对象文件(我们称为“库”,但也称为“ DLL”)上进行操作。 QLibrary以平台无关的方式提供对库中功能的访问。您可以在构造函数中传递文件名,也可以...
  • Qt:QLibrary简析与使用

    千次阅读 2021-02-04 15:29:50
    文档摘要: QLibrary用于动态加载dll,其实例在单个共享对象文件(我们称之为“库”,但也称为“DLL”)上运行,以独立于平台的方式提供对库中功能接口的访问。 使用时应调用load()来加载动态库文件,isLoaded()...
  • 详解 QT源码之 QLibrary跨平台调用动态库实现是本文要讲解的内容,在不同同台上动态库的使用,先来看内容。1、win下动态库调用有关的函数包括:(1)LoadLibrary,装载动态库。(2)GetProcAddress,获取要引入的函数,...
  • int HeartBeatDll(const char *szIp, const int &nPort, int *nCpuUsage, int *nMemUsage) { QLibrary mylib("HttpClientDll.dll"); if(mylib.load()) { HeartBeat open=(HeartBeat)mylib.resolve("HeartBeat"); //...
  • QObject *parent = Q_NULLPTR) QLibrary(constQString &fileName, intverNum, QObject *parent = Q_NULLPTR) QLibrary(constQString &fileName, constQString &version, QObject *parent = Q_NULLPTR) ~QLibrary() ...
  • Qt文档阅读笔记-QLibrary基本概念及实例

    千次阅读 多人点赞 2020-06-16 19:39:45
    QLibrary类是在程序运行时加载动态动态链接库的。 可以通过使用构造函数添加需要加载的链接库路径,或者使用setFileName()函数设置路径。如果是绝对路径就直接加载,如果是相对路径QLibrary会在相当路径及所有...
  • ![图片说明](https://img-ask.csdn.net/upload/202006/11/1591860820_463177.png)
  • 查看相应DLL的依赖库 (1)通过VS自带工具dumpbin,查看DLL的依赖库 dumpbin /dependents **.dll ... QLibrary gbrLib("****.dll"); if(!gbrLib.load()){ qDebug()<<"*******_dll load failed!"<
  • msnh-qlibrary-example-master.zip
  • QT调用动态库,在编译时和运行时的方式不同,编译时可在pro文件加载或使用QLibrary类加载;运行时依赖环境变量,windows下直接把动态库拷贝到可执行文件目录即可,linux需要配置固定路径或相对路径搜索动态库(ps:...
  • QLibrary Class Reference [QtCore module] 该类加载分享的库在运行时。 #include 继承QObject 注意:所有函数是可重入的 公共类型: enum LoadHint { ResolveAllSymbolsHint, ExportExternalSymbolsHint, ...
  • 例一: 萤石开放平台 EZPCOpenSDK_v4.5.1_Build20200605 https://www.cnblogs.com/Q-v-Q/p/13736490.html http://open.ys7.com/doc/zh/book/pc/pc-sdk.html 例二: msnh-qlibrary-example-master.zip
  • QT 使用QLibrary加载动态库

    万次阅读 2019-03-13 17:29:50
    首先将目录切换到QTDIR/src/corelib/plugin,这里面就是QLibrary实现的源代码,打开qlibrary_p.h(熟悉了Qt的常用手法,就知道,这就是QLibrary内部实现的代码),可以看到 bool load_sys(); bool unload_sys...
  • library = new QLibrary(strPath); if(!library->load()) ui->plainTextEdit_data->appendPlainText(library->errorString()); } VS2013 生成的库,是要release,不能是debug。 然后将生成的库放到QT的exe下面 属性...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,274
精华内容 509
关键字:

qlibrary

友情链接: STM32F4SixteenAD.rar