Working with gRPC/C++ in Windows

07 May 2020


Working with open source projects using C/C++, in Windows has always been a pain, especially for beginners. If there is no prebuilt binary for a specific library, then you will find yourself in the hell hole of compiling it in Windows and also their dependencies. On the contrary, if you're in a Linux/macOS environment, it will mostly reduce to a couple of make and make install commands. That's all. Also C++ lacked a widely used stable package manager for a long time. Now it is slowly changing with the advent of new ones such as vcpkg or conan. Here in this article, I'll show you how to set up grpc, protobuf libraries in Windows and to make a simple hello world program using server-client model.

gRPC is an RPC framework provided by Google to enable communication between multiple applications over a network. It does it by conveniently abstracting the complexities of enabling server/client connections from the developer and reducing it to simple remote procedure calls. As a result, the developer can easily make multiple programs talk to each other over a network without going through the hassles of networking programming. This is very useful if you are developing prototypes and you want to make them communicate with each other. gRPC has support for multiple languages and as a result, you can easily make your C++ app to communicate with a Go or Python app, by making use of a common Interface Definition Language(IDL) file. gRPC uses protocol buffers as the Interface Definition Language (IDL) for describing both the service interface and the structure of the payload messages.

Let's take an example with C++ as the language for the server and client. The following components are required for generating the message structures and the service interfaces ,

protoc is a compiler which will take the proto file as the input and generates the message structs and service interfaces in the desired language, in our case, C++.

.proto file is an IDL file where we define the message passing structures and rpc apis according to the Protobuf specifications.

gRPC plugin for the specific language: Separate gRPC plugins exist for different programming languages and these will be required by the protoc for generating the source files based on the service interfaces defined on the IDL.

So now we need to install the gRPC and Protobuf packages in our system.

Installation of vcpkg

The gRPC and Protobuf projects are available in the below-mentioned Github URLs, but to build these from the source for C++ would be a difficult task. Hence we will use a C++ package manager to do this job for us and install the binaries in our system.

https://github.com/grpc/grpc/tree/master/src/cpp
https://github.com/protocolbuffers/protobuf

Another advantage of using a package manager is that the libraries will be compatible with each other mostly. Instead, if you take the latest library code from their project site, then you might face some compatibility issues and you will end up spending time in resolving those. The package manager which we are going to use is vcpkg, a cross-platform open source package manager from Microsoft. It can be downloaded from the Microsoft page in Github. The installation steps are pretty straight forward for vcpkg and one shouldn't face any issues generally.

After the installation, one might have to add the path of vcpkg executable to the PATH variable in Environmental variables to make it available over the console.

Installation of gRPC

In order to install gRPC using vcpkg, launch a console in Windows and execute the following command,

vcpkg install grpc:x64-windows

If you want the 32-bit version, replace grpc:x64-windows with grpc:x86-windows. Now the vcpkg will download the code, compile it in your machine and install the package in the pkg folder inside the vcpkg installation directory.

Installation of protobuf

Similarly, use the vcpkg to install the protobuf library by issuing the following command,

vcpkg install protobuf protobuf:x64-windows

If zlib support is desired, you'll also need to install the zlib feature:

vcpkg install protobuf[zlib] protobuf[zlib]:x64-windows

Note: Ideally, this should go through without any errors if you have a Visual studio version that is installed already.

Once installed, you can find the installed packages in the vcpkg directory under the folder <vcpkg_installed_path>\packages. In order to make the packages available system-wide, you need to issue the command,

vcpkg integrate install

Generation of source files using proto file

Now we have everything we need, so let's try to generate the message and service interfaces from a proto file using the protoc compiler.

I assume that you have CMake installed in your system and that you have a basic understanding of CMake, since I'll be using CMake here for creating the project. You can find an introduction article to CMake here.

First, we'll create a folder for our project with the following structure,

project
|______build
|______proto
| |______helloworld.proto
|
|______src
| |______server.cpp
| |______client.cpp
|______CMakeLists.txt

Now we'll generate the source files from the proto file using protoc compiler.

If protoc is not available from your console, you might have to add it to your system env PATH. And it will be present in your <vcpkg_install_path>\packages\protobuf_x64-windows\bin folder.

For simplicity, let's pull a simple proto file from the gRPC website and we'll use it for our purpose. The proto file can be downloaded from examples/protos/helloworld.proto. To understand the structure of a proto file, visit developers.google.com/protocol-buffers/docs/proto for more details.

Now copy the file to our project/proto folder and run the following commands from there,

protoc -I=. --cpp_out=. helloworld.proto

This will generate the cpp file required for the message structures.

protoc -I=. --grpc_out=. --plugin=protoc-gen-grpc="<vcpkg_install_path>\packages\grpc_x64-windows\tools\grpc\grpc_cpp_plugin.exe" helloworld.proto

This command will generate the cpp file required for the service interfaces.

Creating a project using CMake

Now that we have generated the required files from the proto file, lets add the server, client code and create a project.

The server.cpp and client.cpp will be using the same code mentioned in the example mentioned in the gRPC website. So copy the content to our local server and client cpp files. You have to update the header path of helloworld.grpc.pb.h to the relative path "../proto/helloworld.grpc.pb.h" in both the client and server source files.

Now let's add content to our CMakeLists.txt file. Take the following code and copy it to our CMakeLists.txt file.

cmake_minimum_required( VERSION 3.1 )

project( grpc_example )

find_package(gRPC CONFIG REQUIRED)

find_package( Protobuf REQUIRED )

add_executable( server src/server.cpp proto/helloworld.grpc.pb.cc proto/helloworld.pb.cc)

add_executable( client src/client.cpp proto/helloworld.grpc.pb.cc proto/helloworld.pb.cc)

target_link_libraries( server PRIVATE gRPC::grpc++ gRPC::grpc++_reflection gRPC::gpr gRPC::grpc gRPC::grpc++ protobuf::libprotoc protobuf::libprotobuf protobuf::libprotobuf-lite )

target_link_libraries( client PRIVATE gRPC::grpc++ gRPC::grpc++_reflection gRPC::gpr gRPC::grpc gRPC::grpc++ protobuf::libprotoc protobuf::libprotobuf protobuf::libprotobuf-lite )

Now go to our project/build folder and issue the following command to generate a project using CMake. I'll be generating a Visual Studio 2015 solution here, but the choice is up to you.

cmake -G "Visual Studio 14 2015 Win64" ../ -DCMAKE_TOOLCHAIN_FILE=<vcpkg_install_path>/scripts/buildsystems/vcpkg.cmake

The -DCMAKE_TOOLCHAIN_FILE is required to identify the library and header paths when we use the find_package() API in the CMakeLists file.

Compiling the code and testing the server and client executables

Now once the project is created, we can easily compile it from the console from the build directory using the command,

cmake --build .

This should generate the binaries in the build/Debug folder. Now go to the Debug folder, and run the server.exe and it should give the following output.

$ server.exe
Server listening on 0.0.0.0:50051

Open another console, go to the build/Debug folder and run client.exe. It should give the following output.

$ client.exe
Greeter received: Hello world

That's it. You have successfully created a client-server program using gRPC in Windows. Explaining the structure of this server/client using gRPC classes is beyond the scope of this article and it can be read from the gRPC website directly. I hope you got a fair understanding of setting up the gRPC, protobuf libraries, and how to run an application using it.

You can use gRPC to develop highly scalable apps over a network without actually having to go through the intrinsics of network programming and it is definitely worth to try it at least once.