/**
\page thrift_tutorial_portable Thrift IDL in YARP: writing a portable

\tableofcontents

YARP built-in types can be sent through Ports. Sometimes you need to send custom
datatypes, in YARP objects that can be sent through ports are called `Portable`
objects.
\ref port_expert shows how you can manually implement a portable object.
This tutorial shows how you can automate this process using the Thrift compiler.

\section thrift_tutorial_portable_intro Introduction

Suppose we have two modules that wish to share a `SharedData` struct that
contains a string and a vector.
Normally you would define the data in a C++ header file and write
serialization/deserialization methods to allow it to be sent and received
to/from a port (this process is called marshalling/demarshalling).
This process requires some YARP specific expertise, is error-prone and tedious.
The idea here is that instead of manually writing the class you define the
structure using an intermediate language (the Thrift IDL language), then you ask
a compiler (the yarpidl_thrift compiler) to generate the class for you,
including all the required code.

Let's see how to do it.

\section thrift_tutorial_portable_thirft Thrift definition for `SharedData`

We start by defining our `ShareData` structure. Open a text editor and type
the following:

~~~{.thrift}
struct SharedData {
  1: string text;
  2: list<double> content;
}
~~~

name this file `SharedData.thrift` save and close it.

In thrift's syntax this specifies that `SharedData` is a struct that contains a
\em text field of type \em string and a \em content field which type is a
\em vector of floats.
Thrift in fact supports much more options, see \ref thrift_tutorial.

Now the `yarpidl_thrift` compiler can be invoked to generate both `SharedData.h`
and `SharedData.cpp`.

Type:

~~~{.sh}
yarpidl_thrift --gen yarp --out ./ SharedData.thrift
~~~

This will generate two files: `SharedData.h` and `SharedData.cpp`.

In case you are interested you can inspect them to see that they define a C++
class with some extra code.
The good thing is that you don't actually need to bother about the details, but
you can readily use the class in your code.

Now we can use these files in a YARP program.


\section thrift_tutorial_portable_code Code

This code is straightforward. We define a simple sender executable that open a
port and periodically write a `SharedData` object.

As usual we start with the CMake code, write your `CMakeLists.txt`:

~~~{.cmake}
cmake_minimum_required(VERSION 3.12)

find_package(YARP COMPONENTS os sig REQUIRED)


add_executable(sender)
target_sources(sender PRIVATE sender.cpp SharedData.cpp)
target_include_directories(sender PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(sender PRIVATE YARP::YARP_os
                                     YARP::YARP_sig
                                     YARP::YARP_init)
~~~

Now we write the code for the sender in `sender.cpp`:

~~~{.cpp}
#include "SharedData.h"
#include <iostream>
#include <yarp/os/Network.h>
#include <yarp/os/BufferedPort.h>
#include <yarp/os/Time.h>

using namespace std;

int main()
{
   yarp::os::Network network;

   yarp::os::Port port;

   if (!port.open("/sender"))
   {
       cerr<<"Error opening port, check your yarp network\n";
       return -1;
   }

   cout<<"Starting sender\n";

   while(true)
   {
      SharedData d;

      // d.text is a string
      d.text="Hello from sender";

      //d.content is a vector, let's push some data
      d.content.push_back(0.0);
      d.content.push_back(0.0);

      port.write(d);

      yarp::os::Time::delay(0.1);
   }

   return 0;
}
~~~

Now compile the code

~~~{.sh}
mkdir build
cd build
cmake ../
make

./sender
~~~

Now you can run yarp read on a separate console to inspect the content that is
being transmitted on the port, the output should be something like this:

~~~{.sh}
yarp read ... /sender
~~~
\verbatim
yarp: Port /tmp/port/1 active at tcp://127.0.0.1:10003
yarp: Receiving input from /sender to /tmp/port/1 using tcp
"Hello from sender" (0.0 0.0)
"Hello from sender" (0.0 0.0)
\endverbatim

It is simple to write a receiver:

Append the following to the `CMakeLists.txt`

~~~{.cmake}
add_executable(receiver)
target_sources(receiver PRIVATE receiver.cpp
                                SharedData.cpp)
target_link_libraries(receiver PRIVATE YARP::YARP_os
                                       YARP::YARP_sig
                                       YARP::YARP_init)
~~~

This is the receiver code in `receiver.cpp`:

~~~{.cpp}
#include <SharedData.h>
#include <iostream>
#include <yarp/os/Network.h>
#include <yarp/os/BufferedPort.h>

using namespace std;

int main()
{
   yarp::os::Network network;

   cout<<"Starting receiver\n";

   yarp::os::Port port;
   if (!port.open("/receiver"))
   {
       cerr<<"Error opening port, check your yarp network\n";
       return -1;
   }

   while(true)
   {
       SharedData d;
       port.read(d);

       //access d

   }

   return 0;
}
~~~


\section thrift_tutorial_portable_using_cmake Using CMake

YARP provides CMake supports to automate the invocation of `yarpidl_thrift`.
This is convenient in large projects when we generate several files and we do
not want to keep track of all of them individually.

We can use `yarp_idl_to_dir` to tell CMake to parse `SharedData.thrift` with the
thrift compiler.
All generated files will be placed in separate `include` and `src` directories.

~~~{.cmake}
# compile definition file to generate source code into the desired directory
set(generated_libs_dir "${CMAKE_CURRENT_SOURCE_DIR}")
yarp_idl_to_dir(INPUT_FILES SharedData.thrift
                OUTPUT_DIR ${generated_libs_dir}
                SOURCES_VAR sources
                HEADERS_VAR headers
                INCLUDE_DIRS_VAR include_dirs)


# create the sender
add_executable(sender)
target_sources(sender PRIVATE sender.cpp
                              ${headers}
                              ${sources})
target_include_directories(sender PRIVATE ${include_dirs})
target_link_libraries(sender PRIVATE YARP::YARP_os
                                     YARP::YARP_sig
                                     YARP::YARP_init)

# create the receiver
add_executable(receiver)
target_sources(receiver PRIVATE receiver.cpp
                                ${headers}
                                ${sources})
target_include_directories(receiver PRIVATE ${include_dirs})
target_link_libraries(receiver PRIVATE YARP::YARP_os
                                       YARP::YARP_sig
                                       YARP::YARP_init)
~~~

Now you just have to execute CMake.
The variable `ALLOW_IDL_GENERATION` controls if the thrift compiler is executed
to generate `SharedData.h/cpp` or not.
It will be off by default if there is already generated code in the desired
directory, you'll need to turn it on to overwrite that.

~~~{.sh}
cd build
cmake ../ -DALLOW_IDL_GENERATION=TRUE
~~~

The code generation step is required only when `SharedData.thrift` is modified.


\section thrift_tutorial_portable_related_tutorials Related Tutorials

The Thrift IDL also allows defining modules interfaces, this is explained here:
\li \ref thrift_tutorial_simple
\li \ref thrift_tutorial

YARP supports ROS types.
An alternative method to define portable objects in YARP is to use the ROS
syntax (i.e. through a .msg file).
The disadvantage of this approach is that you cannot use native YARP types, but
the advantage is that your messages will be compatible with ROS and readable
from a topic. This tutorial shows how you do this:

\li \ref rostypes_tutorial_portable

Code for this tutorial can be found here: `example/idl/portable`

*/
