7.2 Hello World with protobuf
In the last section you learned how to send strings to an eCAL Topic. Using strings is great for simple data that has a textual representation. Quite often however your data will be more complex, so you need some kind of protocol that defines how your data is structured.
Of course, you can define your own protocol and pass the raw memory to eCAL (you would use the raw eCAL::CPublisher() to do that). Our recommended way however is to use Google protobuf, because:
- It solves the problem of how to serialize and de-serialize data for you
- You get downward compatibility out of the box (if you follow the guidelines)
- It is maintained by Google and the API is stable
- The eCAL Monitor can display a nice reflection view of the data
7.2.1 Protobuf sender
Let’s implement a small application, that lets the user input his name and send a message to an eCAL topic. As the sender and receiver need the same .proto files, we place them in a separate directory next to the source directories for the sender and the receiver:
Directory
Directoryproto_messages
- hello_world.proto
Directoryprotobuf_snd/
- …
Directoryprotobuf_rec/
- …
Let’s start with the proto_messages/hello_world.proto
file!
1syntax = "proto3";2
3package proto_messages;4
5message HelloWorld6{7 string name = 1;8 uint32 id = 2;9 string msg = 3;10}
Now start implementing the actual sender application. Just as in the last section create the CMakeLists.txt
and main.cpp
in the protobuf_snd
directory and paste the following content:
-
CMakeLists.txt 1cmake_minimum_required(VERSION 3.0)2set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)34project(protobuf_snd)56set(CMAKE_CXX_STANDARD 14)7set(CMAKE_CXX_STANDARD_REQUIRED ON)89find_package(eCAL REQUIRED)10find_package(Protobuf REQUIRED)1112set(source_files13main.cpp14)1516set(protobuf_files17${CMAKE_CURRENT_SOURCE_DIR}/../proto_messages/hello_world.proto18)1920add_executable(${PROJECT_NAME} ${source_files})2122PROTOBUF_TARGET_CPP(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/../proto_messages/ ${protobuf_files})2324target_link_libraries(${PROJECT_NAME}25eCAL::core26protobuf::libprotobuf27) -
main.cpp 1#include <ecal/ecal.h>2#include <ecal/msg/protobuf/publisher.h>34#include <iostream>5#include <thread>67#include "hello_world.pb.h"89int main(int argc, char** argv)10{11// Initialize eCAL and create a protobuf publisher12eCAL::Initialize(argc, argv, "Hello World Protobuf Publisher");13eCAL::protobuf::CPublisher<proto_messages::HelloWorld> publisher("hello_world_protobuf");1415// Ask the user to input his name16std::cout << "Please enter your name: ";17std::string name;18std::getline(std::cin, name);1920unsigned int id = 0;2122// Infinite loop (using eCAL::Ok() will enable us to gracefully shutdown the23// Process from another application)24while (eCAL::Ok())25{26// Let the user input a message27std::cout << "Type the message you want to send: ";28std::string message;29std::getline(std::cin, message);3031// Create a protobuf message object32proto_messages::HelloWorld hello_world_message;33hello_world_message.set_name(name);34hello_world_message.set_msg (message);35hello_world_message.set_id (id++);3637// Send the message38publisher.Send(hello_world_message);39std::cout << "Sent message!" << std::endl << std::endl;40}4142// finalize eCAL API43eCAL::Finalize();44}
Again, you can already watch the sender doing its work by inspecting the topic in the eCAL Monitor! (Compile the application just as in the last section)
7.2.2 Protobuf receiver
-
CMakeLists.txt 1cmake_minimum_required(VERSION 3.0)2set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)34project(protobuf_rec)56set(CMAKE_CXX_STANDARD 14)7set(CMAKE_CXX_STANDARD_REQUIRED ON)89find_package(eCAL REQUIRED)10find_package(Protobuf REQUIRED)1112set(source_files13main.cpp14)1516set(protobuf_files17${CMAKE_CURRENT_SOURCE_DIR}/../proto_messages/hello_world.proto18)1920add_executable(${PROJECT_NAME} ${source_files})2122PROTOBUF_TARGET_CPP(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/../proto_messages/ ${protobuf_files})2324target_link_libraries(${PROJECT_NAME}25eCAL::core26protobuf::libprotobuf27) -
main.cpp 1#include <ecal/ecal.h>2#include <ecal/msg/protobuf/subscriber.h>34#include <iostream>5#include <thread>67#include "hello_world.pb.h"89void HelloWorldCallback(const proto_messages::HelloWorld& hello_world_msg)10{11std::cout << hello_world_msg.name() << " sent a message with ID "12<< hello_world_msg.id() << ":" << std::endl13<< hello_world_msg.msg() << std::endl << std::endl;14}1516int main(int argc, char** argv)17{18// Initialize eCAL and create a protobuf subscriber19eCAL::Initialize(argc, argv, "Hello World Protobuf Subscriber");20eCAL::protobuf::CSubscriber<proto_messages::HelloWorld> subscriber("hello_world_protobuf");2122// Set the Callback23subscriber.AddReceiveCallback(std::bind(&HelloWorldCallback, std::placeholders::_2));2425// Just don't exit26while (eCAL::Ok())27{28std::this_thread::sleep_for(std::chrono::milliseconds(500));29}3031// finalize eCAL API32eCAL::Finalize();33}
Now compile and start both the sender and the receiver application and send some messages!
Congratulations, you have completed the Getting Started chapter! Now go ahead and use eCAL in your real-world scenario.
If you experience issues, you can create a GitHub issue, to get help.
7.2.3 Files
Directory
Directoryproto_messages
Directoryprotobuf_snd
Directoryprotobuf_rec