上篇文章《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. [转]国内阿里Maven仓库镜像Maven配置文件Maven仓库速度快

    原文地址:http://www.cnblogs.com/ae6623/p/4416256.html 国内连接maven官方的仓库更新依赖库,网速一般很慢,收集一些国内快速的maven仓库镜像以备用. ...

  2. [转]JVM系列一:JVM内存组成及分配

    原文地址:http://www.cnblogs.com/redcreen/archive/2011/05/04/2036387.html JVM系列一:JVM内存组成及分配 java内存组成介绍:堆( ...

  3. python的列表元素输出

    1)for循环输出 这种方法是大家最容易想到的,也是最简单的,但是它有一个弊端:它的输出是竖向排列的,而我们往往需要水平输出. >>> for i in [1,2,3]: print ...

  4. Python—文件读写操作

    初识文件操作 使用open()函数打开一个文件,获取到文件句柄,然后通过文件句柄就可以进行各种各样的操作了,根据打开文件的方式不同能够执行的操作也会有相应的差异. 打开文件的方式: r, w, a, ...

  5. 01-路由跳转 安装less this.$router.replace(path) 解决vue/cli3.0语法报错问题

    2==解决vue2.0里面控制台包的一些语法错误. https://www.jianshu.com/p/5e0a1541418b 在build==>webpack.base.conf.j下注释掉 ...

  6. Vue工程化入口文件main.js中Vue.config.productionTip = false含义

    阻止启动生产消息,常用作指令.通俗理解为消息提示的环境配置. 阻止启动生产消息 這又是什麽意思? 看下效果 (1)Vue.config.productionTip = false (2)Vue.con ...

  7. vue组件name的作用小结

    我们在写vue项目的时候会遇到给组件命名 这里的name非必选项,看起来好像没啥用处,但是实际上这里用处还挺多的 ? 1 2 3 export default {    name:'xxx' } 1. ...

  8. [mybatis] sql语句无错误,但是执行多条sql语句时,抛出java.sql.SQLSyntaxErrorException

    错误内容 org.springframework.jdbc.BadSqlGrammarException: ### Error updating database. Cause: java.sql.S ...

  9. ASP.NET开发实战——(十二)ASP.NET MVC 与数据库之Entity Framework Migrations

    在开发数据库应用程序的时候,经常会遇到某些表需要添加字段或者修改类型.新增表等需求,而对于EF Code First来说关注的只有实体类,当需求变更时只需要添加新的实体类或者在实体类中添加.删除.修改 ...

  10. Python Dataframe 分组排序和 Modin

    Python Dataframe 分组排序和 Modin 1.按照其中一列进行排序 在dataframe中,按照其中的一列排序:比如q值倒排 (1)rank方法 data['new_rank'] = ...