# SoftBank Robotics documentation What's new in NAOqi 2.8?

# Porting C++ code from NAOqi1 to NAOqi2

## Introduction

This guide describes how to port c++ modules to NAOqi2. It is not necessary to follow all the steps at once, each step can be done independently, but if you start a section, you must do all the subsections.

## Writing a NAOqi2 service

To create a module, you used to inherit from `ALModule` and register all your methods in your constructor:

    // myservice.h

    class MyService : public AL::ALModule
    {
    public:
      MyService(boost::shared_ptr<AL::ALBroker> pBroker,
          const std::string& name);

      std::string myMethod(int i) const;

      bool myOtherMethod(int i);
    };

    // myservice.cpp

    MyService::MyService(boost::shared_ptr<AL::ALBroker> pBroker,
        const std::string& name)
      : ALModule(pBroker, pName)
    {
      setModuleDescription("This modules does stuff on things");

      functionName("myMethod", getName(), "return a meaningless string");
      addParam("i", "a meaningless integer");
      setReturn("meaningless_string", "the string you asked for");
      BIND_METHOD(MyService::myMethod);

      functionName("myOtherMethod", getName(), "...");
      addParam("i", "...");
      setReturn("value", "...");
      BIND_METHOD(MyService::myOtherMethod);
    }

This now becomes:

    // myservice.h

    class MyService
    {
    public:
      // you can omit the session if you don't need it
      MyService(qi::SessionPtr session);

      /** return a meaningless string
       * \param i a meaningless string
       * \return the string you asked for
       */
      std::string myMethod(int i) const;

      /** ...
       */
      bool myOtherMethod(int i);

    private:
      qi::SessionPtr _session;
    };

    // myservice.cpp

    MyService::MyService(qi::SessionPtr session)
      : _session(session)
    {
      // Don't register your methods here
    }

    // this macro will register your methods
    QI_REGISTER_MT_OBJECT(MyService, myMethod, myOtherMethod);

You will not see the documentation of your methods when calling `qicli` yet.

For more information, or for registering overloaded functions, see guide-cxx-register-classes.

## Creating a NAOqi2 module

### C++ part

After you created your service, you used to create a module by writing a file like:

    // myservicemain.cpp

    // lots of #include

    #ifndef MYSERVICE_IS_REMOTE
    # ifndef ALCALL
    #   ifdef _WIN32
    #     define ALCALL __declspec(dllexport)
    #   else
    #     define ALCALL
    #   endif
    # endif
    #else
    # define ALCALL
    #endif

    # ifdef __cplusplus
    extern "C"
    {
    # endif

    ALCALL int _createModule(boost::shared_ptr<AL::ALBroker> pBroker)
    {
      // init broker with the main broker instance
      // from the parent executable
      AL::ALBrokerManager::setInstance(pBroker->fBrokerManager.lock());
      AL::ALBrokerManager::getInstance()->addBroker(pBroker);

      // create module instances
      AL::ALModule::createModule<MyService>(pBroker, "MyService");

      return 0;
    }

    ALCALL int _closeModule()
    {
      return 0;
    }

    # ifdef __cplusplus
    }
    # endif

    #ifdef MYSERVICE_IS_REMOTE

    int main(int argc, char *argv[])
    {
      // pointer on createModule
      TMainType sig;
      sig = &_createModule;

      // call main
      ALTools::mainFunction("MyService", argc, argv, sig);
    }

    #endif

You can now write a simple `main` function that connects to Naoqi and registers the service. No more need for `MYSERVICE_IS_REMOTE`, the service will always be remote.

    #include <qi/applicationsession.hpp>
    #include <boost/shared_ptr.hpp>

    int main(int argc, char* argv[])
    {
      qi::ApplicationSession app(argc, argv);
      app.start();
      qi::SessionPtr session = app.session();
      session->registerService("MyService", qi::AnyObject(boost::make_shared<MyService>()));
      app.run();
      return 0;
    }

### CMake part

Here is what you used to write in NAOqi1:

    # Creating module launcher binary
    option(MYSERVICE_IS_REMOTE
      "is my service remote?"
      OFF
    )

    if(MYSERVICE_IS_REMOTE)
      add_definitions(" -DMYSERVICE_IS_REMOTE ")
      qi_create_bin(myservice src/myservicemain.cpp)
      qi_use_lib(myservice stuff stuff2)
      qi_stage_bin(myservice)
    else()
      qi_create_lib(
        myservice

        SRC
        src/myservice.h
        src/myservice.cpp
        src/myservicemain.cpp

        MODULE
        SUBFOLDER naoqi
      )
      qi_use_lib(myservice stuff stuff2)
    endif()

Here also, you don’t need to care about being remote or not. This now becomes:

    qi_create_bin(myservice
      SRC myservice.h myservice.cpp main.cpp
      DEPENDS BOOST QI
      )

Now, see Creating a new application outside Choregraphe using the qi Framework to compile and install your service on your robot.

## Calling a service

You can call a NAOqi1 or NAOqi2 service from both NAOqi1 and NAOqi2. In NAOqi1, you used to do:

    boost::shared_ptr<ALProxy> myservice = getParentBroker()->getProxy("MyService");
    std::string val = myservice.call<std::string>("myMethod", 18);

In NAOqi2, this now becomes:

    qi::AnyObject myservice = _session.service("MyService");
    std::string val = myservice.call<std::string>("myMethod", 18);
    // asynchronous version
    qi::Future<std::string> futval = myservice.async<std::string>("myMethod", 18);

It is up to you to store the session somehow. There is no equivalent to `getParentBroker()` or `getRandomBroker()`.

There are no auto-generated specialized proxies yet in NAOqi2.

Note

If you don’t have a Session (because your module is still in NAOqi1), you can get one from `broker->session()`.

## Getting a Session from a Broker

You can get a Session from a broker by using `broker->session()`.

## Subscribing to an event from ALMemory

You don’t need to change the way you subscribe to ALMemory events. The difference is that in NAOqi2, you can subscribe to an event even if you are not a registered service yourself.

    class MyClass {
    public:
      MyClass(SessionPtr session) {
        qi::AnyObject almemory = session->service("ALMemory");
        // keep the object alive
        _subscriber = almemory.call<qi::AnyObject>("subscriber", "Something/MyEvent");
        _subscriber.connect("signal", boost::bind(&MyClass::myCallback, this, _1));
      }
      void myCallback(AL::ALValue value) { /*...*/ }

    private:
      qi::AnyObject _subscriber;
    };

Glossary Site map Index Support Contact Legal Notices