上篇文章《Windows+VS2017使用gRPC》编译出了Windows下可用的gRPC静态lib库文件,在此基础上要想在Qt上使用,需要使用MSVC2017 64bit构建组件进行构建。

grpc-server

新建基于Widget的Qt工程grpc-server

Widget.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

#include <iostream>
#include <memory>
#include <string>

#include <grpcpp/grpcpp.h>

#include "../grpcSetting/helloworld.grpc.pb.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;

// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::Service
{
    Status SayHello(ServerContext *context, const HelloRequest *request,
                    HelloReply *reply) override
    {
        std::string prefix("Hello ");
        reply->set_message(prefix + request->name());
        return Status::OK;
    }
};

class QTextBrowser;
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void startServer();

private:
    QTextBrowser *text;
};

#endif // WIDGET_H

Widget.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 
#include "Widget.h"
#include <QVBoxLayout>
#include <QTextBrowser>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , text(new QTextBrowser())
{
    setWindowTitle(tr("grpc-server"));
    resize();

QVBoxLayout *layout = new QVBoxLayout(this);
    QPushButton *button = new QPushButton("Start");
    connect(button, &QPushButton::clicked, this, &Widget::startServer);
    layout->addWidget(text);
    layout->addWidget(button);
    setLayout(layout);
}

Widget::~Widget()
{

}

void Widget::startServer()
{
    std::string server_address("0.0.0.0:50051");
    GreeterServiceImpl service;

ServerBuilder builder;
    // Listen on the given address without any authentication mechanism.
    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
    // Register "service" as the instance through which we'll communicate with
    // clients. In this case it corresponds to an *synchronous* service.
    builder.RegisterService(&service);
    // Finally assemble the server.
    std::unique_ptr<Server> server(builder.BuildAndStart());
    std::cout << "Server listening on " << server_address << std::endl;
    if (text != nullptr)
    {
        text->setText(QString(tr("Server listening on %1")).arg(server_address.c_str()));
    }

// Wait for the server to shutdown. Note that some other thread must be
    // responsible for shutting down the server for this call to ever return.
    server->Wait();
}

grpc-client

新建基于Widget的Qt工程grpc-client

Widget.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
 
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

#include <iostream>
#include <memory>
#include <string>

#include <grpcpp/grpcpp.h>

#include "../grpcSetting/helloworld.grpc.pb.h"

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;

class GreeterClient
{
public:
    GreeterClient(std::shared_ptr<Channel> channel)
        : stub_(Greeter::NewStub(channel)) {}

// Assembles the client's payload, sends it and presents the response back
    // from the server.
    std::string SayHello(const std::string &user)
    {
        // Data we are sending to the server.
        HelloRequest request;
        request.set_name(user);

// Container for the data we expect from the server.
        HelloReply reply;

// Context for the client. It could be used to convey extra information to
        // the server and/or tweak certain RPC behaviors.
        ClientContext context;

// The actual RPC.
        Status status = stub_->SayHello(&context, request, &reply);

// Act upon its status.
        if (status.ok())
        {
            return reply.message();
        }
        else
        {
            std::cout << status.error_code() << ": " << status.error_message()
                      << std::endl;
            return "RPC failed";
        }
    }

private:
    std::unique_ptr<Greeter::Stub> stub_;
};

class QTextBrowser;
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void req();

private:
    QTextBrowser *text;
};

#endif // WIDGET_H

Widget.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 
#include "Widget.h"
#include <QVBoxLayout>
#include <QTextBrowser>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , text(new QTextBrowser())
{
    setWindowTitle(tr("grpc-client"));
    resize();

QVBoxLayout *layout = new QVBoxLayout(this);
    QPushButton *button = new QPushButton("req");
    connect(button, &QPushButton::clicked, this, &Widget::req);
    layout->addWidget(text);
    layout->addWidget(button);
    setLayout(layout);
}

Widget::~Widget()
{

}

void Widget::req()
{
    // Instantiate the client. It requires a channel, out of which the actual RPCs
    // are created. This channel models a connection to an endpoint (in this case,
    // localhost at port 50051). We indicate that the channel isn't authenticated
    // (use of InsecureChannelCredentials()).
    GreeterClient greeter(grpc::CreateChannel(
                              "localhost:50051", grpc::InsecureChannelCredentials()));
    std::string user("world");
    std::string reply = greeter.SayHello(user);
    std::cout << "Greeter received: " << reply << std::endl;
    if (text != nullptr)
    {
        text->setText(QString("Greeter received: %1").arg(reply.c_str()));
    }

}

Pro文件设置

添加预处理器定义:DEFINES += _WIN32_WINNT=0x0A00

添加链接库以及包含库:这里直接复制过来了,一些冗余的内容可根据实际情况调整

*.pro
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 
INCLUDEPATH += $$PWD/../../../grpc_plugs/grpc/include
INCLUDEPATH += $$PWD/../../../grpc_plugs/grpc/third_party/protobuf/src
DEPENDPATH += $$PWD/../../../grpc_plugs/grpc/include

win32: LIBS += -L$$PWD/../../../grpc_plugs/grpc/.build/Debug/ -lgrpc++
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/Debug/grpc++.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/Debug/libgrpc++.a

win32: LIBS += -L$$PWD/../../../grpc_plugs/grpc/.build/Debug/ -lgrpc
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/Debug/grpc.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/Debug/libgrpc.a

win32: LIBS += -L$$PWD/../../../grpc_plugs/grpc/.build/Debug/ -lgpr
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/Debug/gpr.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/Debug/libgpr.a

win32: LIBS += -L$$PWD/../../../grpc_plugs/grpc/.build/Debug/ -laddress_sorting
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/Debug/address_sorting.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/Debug/libaddress_sorting.a

win32: LIBS += -L$$PWD/../../../grpc_plugs/grpc/.build/third_party/protobuf/Debug -llibprotobufd
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/third_party/protobuf/Debug/libprotobufd.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/third_party/protobuf/Debug/liblibprotobufd.a

win32: LIBS += -L$$PWD/../../../grpc_plugs/grpc/.build/third_party/zlib/Debug -lzlibd
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/third_party/zlib/Debug/zlibd.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/third_party/zlib/Debug/libzlibd.a

win32: LIBS += -L'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/um/x64/' -lWS2_32

INCLUDEPATH += 'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/um/x64'
DEPENDPATH += 'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/um/x64'

win32:!win32-g++: PRE_TARGETDEPS += 'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/um/x64/WS2_32.lib'
else:win32-g++: PRE_TARGETDEPS += 'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/um/x64/libWS2_32.a'

win32: LIBS += -L'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/um/x64/' -lAdvapi32

INCLUDEPATH += 'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/um/x64'
DEPENDPATH += 'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/um/x64'

win32:!win32-g++: PRE_TARGETDEPS += 'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/um/x64/Advapi32.lib'
else:win32-g++: PRE_TARGETDEPS += 'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.17763.0/um/x64/libAdvapi32.a'

win32: LIBS += -L$$PWD/../../../grpc_plugs/grpc/.build/third_party/cares/cares/lib/Debug/ -lcares

INCLUDEPATH += $$PWD/../../../grpc_plugs/grpc/.build/third_party/cares/cares/lib/Debug
DEPENDPATH += $$PWD/../../../grpc_plugs/grpc/.build/third_party/cares/cares/lib/Debug

win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/third_party/cares/cares/lib/Debug/cares.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../grpc_plugs/grpc/.build/third_party/cares/cares/lib/Debug/libcares.a

运行

参考

附录

MinGW使用VS生成的静态库lib文件时,编译不能通过,会提示:
error: No rule to make target '*.a', needed by '*.exe'. Stop.
可见它需要的时*.a的静态库文件,而无法使用*.lib的静态库文件。
但是,MinGW调用linux生成的静态库.a文件,无法链接成功,也无法使用。
网上流传着这样的资料:
首先,下载安装MSYS2:http://www.msys2.org/
(Download and run the installer - "x86_64" for 64-bit, "i686" for 32-bit Windows)
一路“下一步”就可以安装好MSYS2.
然后运行msys2.exe脚本,执行如下命令:
1、pacman -Syu
2、执行完后,关闭终端,重新打开终端执行:pacman -Su
3、pacman -S git
4、pacman -S mingw-w64-i686-grpc
5、pacman -S mingw-w64-i686-qt5
6、pacman -S mingw-w64-i686-qt-creator
之后就可以在安装的qt creator中添加在msys2/mingw32/lib中的grpc静态库和protobuf静态库!!!然后自己根据官网编写简单的C++工程进行测试,只要你库添加的没问题,测试可以通过。
但是,这个叫MSYS2的类Unix环境安装软件很慢,经常出现安装不成功的问题,很不好使!

Windows+Qt使用gRPC的更多相关文章

  1. Windows+QT+Eclipse+MinGW搭建QT开发环境详细教程

     Windows+QT+Eclipse+MinGW搭建QT开发环境详细教程 一.准备工具: QT-SDK for Windows:http://get.qt.nokia.com/qtsdk/qt-sd ...

  2. windows qt 使用c++ posix接口编写多线程程序(真神奇)good

    一.多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序.一般情况下,两种类型的多任务处理:基于进程和基于线程.基于进程的多任务处理是程序的并发执行.基于线程的多任务处理 ...

  3. Windows+Qt+MinGW使用gRPC

    本文参考博客文章Qt gRPC 简单应用进行了亲自尝试,特此记录以下过程,为后人提供经验.我的环境:Windows10 x64需要依赖MSYS2环境(一个类Unix环境,包管理器)MSYS2 gith ...

  4. Windows QT 商业版 试用

    You're about to evaluate Qt Enterprise - the cross-platform application and UI framework used to dev ...

  5. Windows+VS2017使用gRPC

    gRPC官方Windows安装说明: Install Visual Studio 2015 or 2017 (Visual C++ compiler will be used). Install Gi ...

  6. 配置windows qt开发环境

    1.解压缩MinGW-gcc440_1.zip.将解压后的文件夹复制至C盘根目录下.2.安装qt-creator-win-opensource-2.5.2.3.安装qt-win-opensource- ...

  7. windows qt 使用openssl API

    1.下载安装openssl http://dl.pconline.com.cn/download/355862-1.html 版本: OpenSSL(Win32) 1.0.1g 2.配置QT项目文件, ...

  8. windows qt 编译 boost 添加 路径

    win32-msvc2015: { contains(QMAKE_HOST.arch, x86):{ INCLUDEPATH += D:\3SDK\boost_1_61_0 LIBS += -LD:\ ...

  9. Windows Qt 项目中文乱码

    在头文件中加入 #if _MSC_VER >= 1600 #pragma execution_character_set("utf-8") #endif

随机推荐

  1. bacula备份工具

    源码下载:http://www.bacula.org bacula适合数据业务量巨大,每天都在迅速增长,还需要以tar打包方式进行低级备份而且没有异地容灾策略.Bacula是一个完美的增量备份功能,同 ...

  2. 一文解读ARM架构 (转)

    本文主要介绍的是arm架构和x86架构的区别,首先介绍了ARM架构图,其次介绍了x86架构图,最后从性能.扩展能力.操作系统的兼容性.软件开发的方便性及可使用工具的多样性及功耗这五个方面详细的对比了a ...

  3. HBase安装学习

    一.下载安装 $ wget http://archive.cloudera.com/cdh5/cdh/5/hbase-1.2.0-cdh5.7.0.tar.gz $ tar -zxvf hbase-1 ...

  4. [20190520]exp imp on th fly.txt

    [20190520]exp imp on th fly.txt --//以前做的测试,查找浪费许多时间,做1个记录.--//注:仅仅linux 操作系统,bash shell版本不能太低就可以实现,现 ...

  5. TypeScript 学习笔记(一)

    TypeScript: 1.是 JavaScript 的一个超集,支持 ES6 标准 2.由微软开发的自由和开源的编程语言 3.设计目标是开发大型应用,它可编译成纯 JavaScript,编译出来的 ...

  6. ACM-ICPC 2018 南京赛区网络预赛 I. Skr(回文树)

    题意 https://nanti.jisuanke.com/t/A1955 求所有本质不同的回文串转成数后的和. 思路 如果了解回文树的构造原理,那么这题就很简单了,回文树每个结点代表一个回文串,每添 ...

  7. postman---postman增加断言

    我们在做测试的时候都会有一个验证点,我们通常把这个验证点叫做断言,断言通过了就会说明我们的这个用例是通过的,当然这么强大的postman也是有断言的,我们一起学习下如何通过postman增加断言. 断 ...

  8. fiddler---Fiddler接口测试

    前面介绍了Fiddler一些简单的使用功能,Fiddler不仅可以抓包也可以做接口工具使用,在没有接口文档的时候我们也可以通过Fiddler查看接口具体有哪些内容 Fiddler发送请求 在Fiddl ...

  9. XposedInstaller 是如何安装的

    Launcher 如何通过startActivity 传送一个 intent 到 zygote 如何 接收到它并且 fork出该app的进程的? 安装框架的时候会现有各种检查,比如当前系统版本等 下载 ...

  10. grep: /usr/include/php/main/php.h: No such file or directory

    异常 grep: /usr/include/php/main/php.h: No such file or directory grep: /usr/include/php/Zend/zend_mod ...