Aldebaran documentation What's new in NAOqi 2.4.3?

C++ - How to write a qimessaging service

This document will teach you how to write your very own qimessaging service, so that your new shiny object can be used by other qimessaging services and clients, locally or remotely, and from many different programming languages.

Limitations

There are some restrictions on what you can do:

  • Do not use class member data.
  • Output parameters are not supported: you should not take pointers as arguments, or non-const references.
  • Do not use methods in transmitted struct, as they will not be available in other languages: put the methods in an associated class.

To understand those restrictions, keep in mind that qimessaging is a middleware that knows how to transport data (like primitive types, structs, and containers of the above), and how to make calls to remote methods, signals and properties, but cannot mix the two.

Write your service

Your service can be a simple class which is registered in the type system (see type registration

#include <qi/anyobject.hpp>

struct Mosquito
{
  double yaw,theta,distance;
};
QI_TYPE_STRUCT(Mosquito, yaw, theta, distance)

class Cat
{
  public:
    void meow(int volume);
    bool setTarget(const Mosquito& m);

    qi::Property<float> hunger;
    qi::Property<float> boredom;
    qi::Property<float> cuteness;
    qi::Signal<Mosquito> onTargetDetected;
};
QI_REGISTER_OBJECT(Cat, meow, setTarget, hunger, boredom, cuteness,
    onTargetDetected);

Sessions and ServiceDirectory

Sessions may be listening and/or connected to other sessions. In a group of sessions, one and only one ServiceDirectory must be registered which will keep track of all registered services. Usually, one session is used as a server with listenStandalone() and other sessions are used as client with connect().

listenStandalone() is the same function as listen() but it will also register a ServiceDirectory on the session.

Registering your service on a ServiceDirectory

You can then instantiate your object and expose it on a session. It does not matter whether your session is a listener or a client. In this example, ApplicationSession parses the command line arguments to find out what the user wants, i.e.:

  • which type of session (listening or connected to a ServiceDirectory)
  • on which address
#include <qi/applicationsession.hpp>

int main(int argc, char** argv)
{
  qi::ApplicationSession app(argc, argv);

  app.start();

  qi::SessionPtr session = app.session();

  boost::shared_ptr<Cat> cat = boost::make_shared<Cat>();
  session->registerService("CatService", cat);

  app.run();
}

The session will keep a reference on cat until it’s closed or CatService is unregistered.