Qt中使用Protobuf简单案例(Windows + msvc)

编译protobuf

首先下载protobuf源代码
使用cmake,配置相关路径和配置
注意选择生成动态链接库,在windows上最好勾选动态链接库,否则会出现很多麻烦
在这里插入图片描述
点Generate,生成VS的工程文件。
然后打开vs,选择release或debug在这里插入图片描述
点击解决方案直接右键选择生成解决方案即可。
注意:debug生成的库在Qt中只能在debug下使用,release生成的库只能在release下使用
在这里插入图片描述

Qt中使用Protobuf

编写.proto文件,使用protoc.exe编译成.h和.cc文件
将生成的.h和.cc文件复制到项目目录下
在这里插入图片描述
在项目根目录下新建protobuf目录,然后进入protobuf下创建include和lib目录,include目录包括protobuf源代码下的src下的google整个文件夹,lib下包括你VS编译后生成的.lib和.dll文件,在你的cmake设置的输出目录下的Debug或者release目录下,如下:
在这里插入图片描述
在这里插入图片描述
现在,创建一个Qt的widget项目,右键点击添加库
在这里插入图片描述
将你lib下的libprotobuf加入,include下位头文件声明
可以看到在.pro中加入了以下配置

# ==========protobuf==========
win32: LIBS += -L$$PWD/protobuf/lib/ -llibprotobuf
INCLUDEPATH += $$PWD/protobuf/include
DEPENDPATH += $$PWD/protobuf/include

然后编译时候根据你的库是release还是debug选择性编译

简单的案例

.proto 文件

syntax = "proto3";
package tutorial;

message Person {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;
}

.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = protoTest
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

CONFIG += c++11

SOURCES += \
        main.cpp \
        person.pb.cc \
        widget.cpp

HEADERS += \
        person.pb.h \
        widget.h

FORMS += \
        widget.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

# ==========protobuf==========
DEFINES += PROTOBUF_USE_DLLS


win32: LIBS += -L$$PWD/protobuf/lib/ -llibprotobuf

INCLUDEPATH += $$PWD/protobuf/include
DEPENDPATH += $$PWD/protobuf/include

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "person.pb.h"
#include <sstream>
#include <QFile>
#include <QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    GOOGLE_PROTOBUF_VERIFY_VERSION;
    tutorial::Person person;
    person.set_id(123456);
    person.set_name("Mark");
    person.set_email("137782866@qq.com");
    //write
    QFile file_out(QCoreApplication::applicationDirPath() + "/person.pb");
    if(!file_out.open(QIODevice::WriteOnly)) {
        qDebug() << "can not open file";
    }

    std::ostringstream streamOut;

    person.SerializeToOstream(&streamOut);
    QByteArray byteArray(streamOut.str().c_str());

    QDataStream out(&file_out);
    out << byteArray.length();
    out.writeRawData(byteArray.data(), byteArray.length());
    file_out.close();

    //read
    QFile file_in(QCoreApplication::applicationDirPath() + "/person.pb");
    if(!file_in.open(QIODevice::ReadOnly)) {
         qDebug() << "can not open file";
    }

    QDataStream in(&file_in);
    int dataLength = 0;
    in >> dataLength;

    QByteArray byteArray2;
    byteArray2.resize(dataLength);
    in.readRawData(byteArray2.data(), dataLength);
    tutorial::Person person2;
    if (!person2.ParseFromArray(byteArray2.data(), byteArray2.size())) {
      qDebug() << "Failed to parse person.pb.";
    }

    qDebug() << "ID: " << person.id();
    qDebug() << "name: " << QString::fromStdString(person.name());
    if (person.has_email()) {
        qDebug() << "e-mail: " << QString::fromStdString(person.email());
    }
    file_in.close();
}

Widget::~Widget()
{
    delete ui;
}

运行结果:

ID:  123456
name:  "Mark"
e-mail:  "137782866@qq.com"

遇到的问题

记录一下自己遇到的问题:
问题1:动态库版本和静态库版本使用一样,都是添加libprotobufd.lib,但动态库版本在Qt中编译会爆出这样的错误:

error: LNK2001: 无法解析的外部符号 "class google::protobuf::internal::ExplicitlyConstructed<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > google::protobuf::internal::fixed_address_empty_string" (?fixed_address_empty_string@internal@protobuf@google@@3V?$ExplicitlyConstructed@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@123@A)

解决方案:

  1. 根据你编译的的库看你Qt编译debug还是release下
  2. 尝试在.pro中添加DEFINES += PROTOBUF_USE_DLLS

静态库版本的protoc.exe和动态库版本protoc.exe对.proto处理后生成的文件是相同的。这个是自己做实验得到的结果。
问题2:windows + Qt 中使用protobuf静态库版本遇到的问题:
在这里插入图片描述
这就是为什么在windows上要编译动态库了,静态库试了一下总会出现这样的问题,参考网友在.pro中添加了MTd方式,继续出现这样的问题,原因可能是和免费的Qt使用的是动态库版本有关

参考

posted @ 2020-03-29 20:59  WindSun  阅读(1893)  评论(0编辑  收藏  举报
博客已停更,文章已转移,点击访问