上篇文章《Windows+VS2017使用gRPC》編譯出了Windows下可用的gRPC靜態lib庫文件,在此基礎上要想在Qt上使用,須要使用MSVC2017 64bit構建組件進行構建。html
新建基於Widget的Qt工程grpc-serverlinux
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 |
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( 320 , 460 ); 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(); } |
新建基於Widget的Qt工程grpc-clientios
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 |
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( 320 , 460 ); 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())); } } |
添加預處理器定義:DEFINES += _WIN32_WINNT=0x0A00c++
添加連接庫以及包含庫:這裏直接複製過來了,一些冗餘的內容可根據實際狀況調整git
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腳本,執行以下命令:
一、pacman -Syu
二、執行完後,關閉終端,從新打開終端執行:pacman -Su
三、pacman -S git
四、pacman -S mingw-w64-i686-grpc
五、pacman -S mingw-w64-i686-qt5
六、pacman -S mingw-w64-i686-qt-creator
以後就能夠在安裝的qt creator中添加在msys2/mingw32/lib中的grpc靜態庫和protobuf靜態庫!!!而後本身根據官網編寫簡單的C++工程進行測試,只要你庫添加的沒問題,測試能夠經過。
可是,這個叫MSYS2的類Unix環境安裝軟件很慢,常常出現安裝不成功的問題,很很差使!github