• Windows+Qt使用gRPC


    上篇文章《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(
    320460);

        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(
    320460);

        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环境安装软件很慢,经常出现安装不成功的问题,很不好使!

  • 相关阅读:
    设计模式二(建造者、原型、桥接)
    MSSQL根据表名动态分页的存储过程以及C#.net调用使用
    查询身份证号码信息(C#.NET)
    初试三层+抽象工厂代码生成器
    NET多线程与异步编程
    【SQL.SERVER.DMVS.实战】学习笔记
    【SQL.SERVER.DMVS.实战】学习笔记(二)
    SQL Server 2005数据文件数据的存储
    ASP.NET第九天加强课程
    ASP.NET第四天加强课程
  • 原文地址:https://www.cnblogs.com/MakeView660/p/11512346.html
Copyright © 2020-2023  润新知