加载中…
个人资料
一去二三里
一去二三里
  • 博客等级:
  • 博客积分:0
  • 博客访问:2,322,840
  • 关注人气:898
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

Qt之创建并使用共享库

(2015-08-29 09:58:16)
标签:

qt

qlibrary

共享库

动态链接库

qt共享库

分类: Qt
    关于共享库的创建网上有很多教程,当然,我还是喜欢看官方的文档,可参考:How to create a library with Qt and use it in an application.
    什么是共享库呢?其实就是我们常说的动态链接库。
    动态链接库和静态链接的区别又是什么?

区别一:
  • 动态链接就是把调用函数所在的DLL和调用函数在文件中的位置等信息链接进主程序,程序运行的时候再从DLL中寻找相应函数代码,因此需要相应DLL文件的支持。 静态链接库是把LIB文件中用到的函数代码直接链接进主程序,程序运行时不再需要其它库文件。
  • 动态链接库和静态链接库都是共享代码的方式,如果采用静态链接库,LIB中的指令全部被直接包含在最终生成的 EXE 文件中。但是若使用DLL,该DLL不必被包含在最终EXE文件中,EXE文件执行时可以“动态”引用和卸载这个与EXE独立的DLL文件。
区别二:
  • 动态链接库中可以再包含其它动态或静态链接库。
  • 静态链接库中不能再包含其它动态或者静态链接库。
使用及发布:
    静态链接库,虽然效率高点,且发布简单,但可执行程序较大。。。
    动态链接库:相关联的库以DLL的形式引用,不被包含进可执行程序,发布不方便(需要将每一个DLL都添加到安装包中),但可执行程序较小。。。而且共享库的一个好处是可以动态加载,也就是说,如果涉及到软件升级,那么简单的替换掉相应的DLL就行,不需要重新安装整个程序。

    下面我们来说说Qt中如何创建共享库并应用到程序当中。
1、文件->新建文件或项目
2、选择库->C++库
Qt之创建并使用共享库

3、选择共享库(Shared library)
4、然后傻瓜式的下一步
Qt之创建并使用共享库

5、选择所需要的模块(这里我选择了core、gui、widgets,大家根据各自的情况来选依赖的模块)
Qt之创建并使用共享库

  • SharedLibrary.pro

QT       += widgets

TARGET = SharedLibrary
TEMPLATE = lib

DEFINES += SHAREDLIBRARY_LIBRARY

HEADERS += sharedlibrary.h\
        sharedlibrary_global.h

SOURCES += sharedlibrary.cpp
TEMPLATE = lib 定义生成的为库文件(如果是app则为可执行程序)

完成所有步骤之后,系统会自动生成一个{projectName}_global.h文件
  • sharedlibrary_global.h

#ifndef SHAREDLIBRARY_GLOBAL_H
#define SHAREDLIBRARY_GLOBAL_H

#include 

#if defined(SHAREDLIBRARY_LIBRARY)
#  define SHAREDLIBRARYSHARED_EXPORT Q_DECL_EXPORT
#else
#  define SHAREDLIBRARYSHARED_EXPORT Q_DECL_IMPORT
#endif

#endif // SHAREDLIBRARY_GLOBAL_H
    此文件定义了两个宏SHAREDLIBRARYSHARED_EXPORT,这里的LIB就是工程名字。如果定义了 SHAREDLIBRARY_LIBRARY,SHAREDLIBRARYSHARED_EXPORT定义为Q_DECL_EXPORT,否则定义为 Q_DECL_IMPORT。其实看名字,就知道是把对象导出的语句。
    然后来开始编写我们的库文件。功能主要是获取一个窗体,并实现窗体的随机更换背景色功能,以及求和函数。
  • sharedlibrary.h

#ifndef SHAREDLIBRARY_H
#define SHAREDLIBRARY_H

#include "sharedlibrary_global.h"
#include 

class SHAREDLIBRARYSHARED_EXPORT SharedLibrary : public QWidget
{
    Q_OBJECT
public:
    explicit SharedLibrary(QWidget *parent = 0);
    void updateBackground();
    int subtract(int a, int b);

private slots:
    void onClicked();
};

extern "C" {
    SHAREDLIBRARYSHARED_EXPORT SharedLibrary* getSharedLibrary(); //获取类SharedLibrary对象
    SHAREDLIBRARYSHARED_EXPORT int add(int a, int b);  //自定义的外部函数
}

#endif // SHAREDLIBRARY_H
    注:Class后紧跟着SHAREDLIBRARYSHARED_EXPORT这个宏。简单的理解就是,我需要把SharedLibrary这个类导出。其实就是将其编译成一个DLL文件,其它的类可以使用这个导出类。
  • sharedlibrary.cpp

#include "sharedlibrary.h"
#include 
#include 
#include 

SharedLibrary::SharedLibrary(QWidget *parent)
    : QWidget(parent)
{
    QPushButton *pButton = new QPushButton(this);
    pButton->setText("Test Shared Library");

    connect(pButton, SIGNAL(clicked()), this, SLOT(onClicked()));
}

void SharedLibrary::onClicked()
{
    QMessageBox::information(this, "Tip", "Shared Library...");
}

void SharedLibrary::updateBackground()
{
    QTime time;
    time = QTime::currentTime();
    qsrand(time.msec() + time.second()*1000);

    int nR = qrand() % 256;
    int nG = qrand() % 256;
    int nB = qrand() % 256;

    QPalette palette(this->palette());
    palette.setColor(QPalette::Background, QColor(nR, nG, nB));
    this->setPalette(palette);
}

int SharedLibrary::subtract(int a, int b)
{
    return a - b;
}

SharedLibrary* getSharedLibrary()
{
    return new SharedLibrary();
}

int add(int a, int b)
{
    return a + b;
}

    执行qmake,然后构建,会生成一个SharedLibrary.dll和SharedLibrary.lib文件。这样我们的创建共享库就彻底完成了。

    下面我们来看看如何去应用这个共享库:
    首先新建一个测试工程,然后新建一个文件夹SharedLibrary,并将将刚才生成的文件(SharedLibrary.dll、SharedLibrary.lib、sharedlibrary.h、sharedlibrary_global.h)拷贝到该目录下(也可以不拷贝,这里为了更清楚地说明路径及引用)。
  • TestSharedLibrary.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = TestSharedLibrary
TEMPLATE = app

INCLUDEPATH += ./SharedLibrary

#LIBS += $$PWD/SharedLibrary/SharedLibrary.lib
        #-L$$PWD/SharedLibrary -lSharedLibrary
LIBS += -L$$PWD/SharedLibrary -lSharedLibrary
#$$PWD/SharedLibrary/SharedLibrary.dll

SOURCES += main.cpp
    INCLUDEPATH是包含目录,类似于VS中的附加包含目录。
    LIBS相当于VS中的附加依赖库,不同的是可以通过-L指定库目录,-l指定库名。其间没有空格的。例如上面的-L$$PWD/SharedLibrary -lSharedLibrary代表当前路径下的SharedLibrary目录中的SharedLibrary库,SharedLibrary没有说明.dll还是.lib是让Qt帮我们来做,你也可以指定.lib或者.dll。 

    下面我们看真正的使用吧!真是千呼万唤始出来。。。
  • main.cpp

#include "sharedlibrary.h"
#include 
#include 
#include 
#include 

typedef SharedLibrary* (*GetSharedLibrary)();//定义函数指针,获取类TestDLL对象;
typedef int (*Fun)(int, int); //定义函数指针,int add(int a,int b);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
//    SharedLibrary w;
//    w.resize(400, 200);
//    w.updateBackground();
//    w.show();

//    int nSubtract = w.subtract(10, 4);
//    int nAdd = add(5, 5);
//    QMessageBox::information(NULL, "Tip", QString("subtract:%1  add:%2").arg(nSubtract).arg(nAdd));

    //声明所用到的dll文件
    QLibrary mylib("D:/Works/Test/TestSharedLibrary/SharedLibrary/SharedLibrary.dll");

    //判断是否正确加载
    if (mylib.load())
    {
        qDebug() << "library loaded";

        GetSharedLibrary getSharedLibrary = (GetSharedLibrary)mylib.resolve("getSharedLibrary");
        Fun add = (Fun)mylib.resolve("add");
        if (getSharedLibrary)
        {
            SharedLibrary *pLib = getSharedLibrary();
            pLib->updateBackground();
            pLib->subtract(10, 4);
            pLib->show();
            pLib->setWindowTitle("Test ShareLibrary");
        }
        else
        {
            qDebug() << "Could not show widget from the loaded library";
        }

        if (add)
        {
            int nResult = add(5, 5);
            QMessageBox::information(NULL, "Tip", QString::number(nResult));
        }
        else
        {
            qDebug() << "Could not add from the loaded library";
        }
    }
    //加载失败
    else
    {
        qDebug() << mylib.errorString();
    }
    return a.exec();
}
    上面的代码有一部分注释掉了,因为调用存在多种方式(使用.lib或者加载dll),都可以!
    QLibrary使用起来相当简单,最基本需要知道4个函数load()、isLoad()、 resolve()和unload(),当然,绝大部分情况下,这四个也就够了。load()加载库、isLoad()判断库是否加载成功、resolve()解析库中的函数、unload()卸载库。
   注:运行打包的时候要把相应的DLL也拷贝进去,否则会提示:无法启动此程序,因为计算机中丢失*.dll。

效果如下:
    Qt之创建并使用共享库


注:
    技术在于交流、沟通,转载请注明出处并保持作品的完整性。

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有