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

# Example: HelloWorld module (DEPRECATED)

<< return to C++ examples

The whole example is available here: `helloworld.zip`

## Module creation

This module is defined in the two following files:

### Header

The first one is a header file, defining the HelloWorld class. Note that it is inheriting from the ALModule class.

`helloworld.h`

    /**
     * Copyright (c) 2011 Aldebaran Robotics
     */

    #ifndef HELLOWORLD_H
    #define HELLOWORLD_H

    #include <boost/shared_ptr.hpp>
    #include <alcommon/almodule.h>

    namespace AL
    {
      // This is a forward declaration of AL:ALBroker which
      // avoids including <alcommon/albroker.h> in this header
      class ALBroker;
    }

    /**
     * A simple example module that says "Hello world" using
     * text to speech, or prints to the log if we can't find TTS
     *
     * This class inherits AL::ALModule. This allows it to bind methods
     * and be run as a remote executable or as a plugin within NAOqi
     */
    class HelloWorld : public AL::ALModule
    {
      public:
        HelloWorld(boost::shared_ptr<AL::ALBroker> pBroker, const std::string& pName);

        virtual ~HelloWorld();

        /** Overloading ALModule::init().
        * This is called right after the module has been loaded
        */
        virtual void init();

        /**
         * Make Nao say "Hello world" or just print a message to
         * the console if not connected to a robot.
         */
        void sayHello();

        /**
        * Make Nao say a sentence given in argument.
        */
        void sayText(const std::string& toSay);

        /**
        * Make Nao say a sentence and return its length.
        */
        int sayTextAndReturnLength(const std::string &toSay);

    };
    #endif // HELLOWORLD_H

### Source file

The second one contains the implementation. Note the binding of the functions in the constructor. This binding is imperative: else, the methods won’t be available from outside the module.

`helloworld.cpp`

    /**
     * Copyright (c) 2011 Aldebaran Robotics
     */

    #include "helloworld.h"
    #include <iostream>
    #include <alcommon/albroker.h>
    #include <qi/log.hpp>
    #include <alproxies/altexttospeechproxy.h>

    using namespace AL;

    HelloWorld::HelloWorld(boost::shared_ptr<ALBroker> broker, const std::string& name):
      ALModule(broker, name)
    {
      /** Describe the module here. This will appear on the webpage*/
      setModuleDescription("A hello world module.");

      /** Define callable methods with their descriptions:
      * This makes the method available to other cpp modules
      * and to python.
      * The name given will be the one visible from outside the module.
      * This method has no parameters or return value to describe
      */
      functionName("sayHello", getName(), "Say hello to the world");
      BIND_METHOD(HelloWorld::sayHello);

      functionName("sayText", getName(), "Say a given sentence.");
      /**
      * This enables to document the parameters of the method.
      * It is not compulsory to write this line.
      */
      addParam("toSay", "The sentence to be said.");
      BIND_METHOD(HelloWorld::sayText);

      functionName("sayTextAndReturnLength", getName(),
                   "Say a given sentence, and return its length");
      addParam("toSay", "The sentence to be said.");
      /**
      * This enables to document the return of the method.
      * It is not compulsory to write this line.
      */
      setReturn("sentenceLength", "Length of the said sentence.");
      BIND_METHOD(HelloWorld::sayTextAndReturnLength);

      // If you had other methods, you could bind them here...
      /** Bound methods can only take const ref arguments of basic types,
      * or AL::ALValue or return basic types or an AL::ALValue.
      */
    }

    HelloWorld::~HelloWorld() {}

    void HelloWorld::init()
    {
      /** Init is called just after construction.
      *
      * Here we call sayHello, so that the module does something
      * without us having to explicitly call sayHello from somewhere else.
      */
      sayHello();
    }

    void HelloWorld::sayHello()
    {
      const std::string phraseToSay("Hello world");
      std::cout << "Saying hello to the console ..." << std::endl;
      std::cout << phraseToSay << std::endl;
      std::cout << "Calling say method of ALTextToSpeech module ..." << std::endl;
      try
      {
        /** Create a proxy to TTS.*/
        ALTextToSpeechProxy tts(getParentBroker());
        /** Call the say method. */
        tts.say(phraseToSay);
        /** Note: on the desktop you won't hear anything, but you should see
        * some logs on the naoqi you are connected to.
        */
      }
      catch(const AL::ALError&) // no object name given to avoid warning
      {
        qiLogError("module.example") << "Could not get proxy to ALTextToSpeech" << std::endl;
      }

      qiLogInfo("module.example") << "Done !" << std::endl;
    }

    void HelloWorld::sayText(const std::string &toSay) {
      std::cout << "Saying the phrase in the console..." << std::endl;
      std::cout << toSay << std::endl;
      try
      {
        /** Create a proxy to TTS.*/
        ALTextToSpeechProxy tts(getParentBroker());
        /** Call the say method. */
        tts.say(toSay);
        /** Note: on the desktop you won't hear anything, but you should see
        * some logs on the naoqi you are connected to. */
      }
      catch(const AL::ALError&)
      {
        qiLogError("module.example") << "Could not get proxy to ALTextToSpeech" << std::endl;
      }
    }

    int HelloWorld::sayTextAndReturnLength(const std::string &toSay) {
      /** Say the sentence.*/
      sayText(toSay);
      /** Return its length.*/
      return toSay.length();
    }

### Main

The main.cpp contains lots of boilertemplate code. You should not worrying about this file. Just do not modify it unless you know what you are doing.

`main.cpp`

    /**
     * Copyright (c) 2010 Aldebaran Robotics
     */

    #ifndef _WIN32
    # include <signal.h>
    #endif

    #include <alcommon/albroker.h>
    #include <alcommon/albrokermanager.h>
    #include <alcommon/altoolsmain.h>
    #include "helloworld.h"

    #ifdef HELLOWORLD_IS_REMOTE
    # define ALCALL
    #else
    // when not remote, we're in a dll, so export the entry point
    # ifdef _WIN32
    #  define ALCALL __declspec(dllexport)
    # else
    #  define ALCALL
    # endif
    #endif

    extern "C"
    {
      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<HelloWorld>(pBroker, "HelloWorld");
        return 0;
      }

      ALCALL int _closeModule(  )
      {
        return 0;
      }
    } // extern "C"

    #ifdef HELLOWORLD_IS_REMOTE
      int main(int argc, char *argv[])
      {
        // pointer to createModule
        TMainType sig;
        sig = &_createModule;
        // call main
        return ALTools::mainFunction("HelloWorld", argc, argv, sig);
      }
    #endif

Note: if you want to understand what this `main.cpp` does or want to change it, you can read about it in the Creating a custom main section.

### CMakeLists.txt

The CMakeLists.txt file can generate a .sln file or a Makefile project for you. Do not change it unless you know what you are doing.

`CMakeLists.txt`

    # Copyright (C) 2011 Aldebaran Robotics
    cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR)

    # Define the name of the project
    project(helloworld)

    # This include enable you to use qibuild framework
    find_package(qibuild)

    # Create an option to make is possible compiling the module
    # as a remote executable, or as a local shared library
    option(HELLOWORLD_IS_REMOTE
      "module is compiled as a remote module (ON or OFF)"
      ON)

    # Create a list of source files
    set(_srcs
      helloworld.cpp
      helloworld.h
      main.cpp
    )

    if(HELLOWORLD_IS_REMOTE)
      # Add a compile flag because code changes a little bit
      # when we are compiling an executable
      # This will let you use #ifdef HELLOWORLD_IS_REMOTE
      # in the C++ code
      add_definitions( " -DHELLOWORLD_IS_REMOTE ")

      # Create an executable
      qi_create_bin(helloworld ${_srcs})
    else()
      # Create a plugin, that is a shared library, and make
      # sure it is built in lib/naoqi, so that the naoqi executable
      # can find it later
      qi_create_lib(helloworld SHARED ${_srcs} SUBFOLDER naoqi)
    endif()

    # Tell CMake that sayhelloworld depends on ALCOMMON and
    # ALPROXIES.
    # This will set the libraries to link sayhelloworld with,
    # the include paths, and so on
    qi_use_lib(helloworld ALCOMMON ALPROXIES)

    # Also create a simple executable capable of creating
    # a proxy to the helloworld module
    qi_create_bin(testhelloworld testhelloworld.cpp)
    qi_use_lib(testhelloworld ALCOMMON ALPROXIES)

#### Module access

Here is an example on how to access or “HelloWorld” module from the outside.

`testhelloworld.cpp`

    /**
    * Copyright (c) 2011 Aldebaran Robotics. All Rights Reserved
    *
    * \file testhelloworld.cpp
    * \brief Test how to call a module from the outside.
    *
    * An example on how to call the example "HelloWorld" module from the outside.
    *
    */

    #include <iostream>
    #include <alerror/alerror.h>
    #include <alcommon/alproxy.h>
    #include <alcommon/albroker.h>

    int main(int argc, char* argv[]) {
      if(argc != 2)
      {
        std::cerr << "Wrong number of arguments!" << std::endl;
        std::cerr << "Usage: testhelloworld NAO_IP" << std::endl;
        exit(2);
      }

      const std::string robotIP = argv[1];
      int port = 9559;

      try {
        /** Create a generic proxy to "HelloWorld" module.
        * Arguments for the constructor are
        * - name of the module
        * - string containing the IP adress of the robot
        * - port (default is 9559)
        */
        boost::shared_ptr<AL::ALBroker> broker =
          AL::ALBroker::createBroker("MyBroker", "", 0, robotIP, port);

        boost::shared_ptr<AL::ALProxy> testProxy
          = boost::shared_ptr<AL::ALProxy>(new AL::ALProxy(broker, "HelloWorld"));

        /** Call the sayHello method from the module using its bound name.
        * Since it returns nothing, use the callVoid method.
        */
        testProxy->callVoid("sayHello");

        /** Call the sayText method from the module using its bound name and giving
        * the right argument. Since it returns nothing, use the callVoid method.
        */
        testProxy->callVoid("sayText", std::string("This is a test."));

        /** Call the sayTextAndReturnLength method from the module using its bound
        * name and giving the right argument.
        * Since the method returns something, use the call method templated with
        * the right return type.
        */
        int sentenceLength = testProxy->call<int>("sayTextAndReturnLength",
                             std::string("This is another test"));
        std::cout << "Sentence length is " << sentenceLength << std::endl;
      }
      catch (const AL::ALError& e) {
        std::cerr << e.what() << std::endl;
      }
    }

Glossary Site map Index Support Contact Legal Notices