Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
arcs2:creating_a_component_library [2013/08/20 16:44]
didier
arcs2:creating_a_component_library [2013/08/21 16:08] (current)
didier [Embedding components into a library]
Line 1: Line 1:
 +====== Creating a component library ======
 +For this tutorial, we will only work at creating native ARCS components.
 +We will describe how we design components and store them into libraries.
 +To begin with, ARCS is heavily relying on Qt, so component description
 +will share many similarities with the writing of customized ​
 +[[http://​qt-project.org/​doc/​qt-5.1/​qtcore/​qobject.html|QObjects]] ​
 +with
 +specific [[http://​qt-project.org/​doc/​qt-5.1/​qtcore/​signalsandslots.html|signals and slots]].
 +We will document the steps needed to produce a library like the ''​sample''​ one.
 +
 +===== Designing components =====
 +We will write two components. The first one will be a **Loop** which take as a parameter an iteration number ​
 +and that will execute its iterations. Each iteration will emit a signal indicating the current iteration. ​
 +At the end, the component will emit a particular signal in order to indicate the loop is finished.
 +The second component will receive an integer value and display it in console (component named **DisplayInt**).
 +The declaration of these components should be as follows:
 +<file cpp sample.h>​
 +#include <​QObject> ​
 +
 +class Loop : public QObject // required public inheritance to QObject
 +{
 +  Q_OBJECT // Mandatory macro to create custom signals and slots
 +  public:
 +    // Constructor with a specific required signature
 +    Loop(QObject* parent=0) : QObject(parent) {} 
 +
 +  public slots: // start of slot declarations
 +    void setIterations(int n); // gives the number of iterations to perform
 +
 +  signals: ​     // start of signals declarations
 +    void newIteration(int i);  // signal emitted at each iteration
 +    void sendToken(QString s); // signal emitted at the end of the loop
 +};
 +
 +class DisplayInt : public QObject
 +{
 +  Q_OBJECT
 +  public:
 +    DisplayInt(QObject* parent=0) : QObject(parent) {}
 +
 +  public slots:
 +    void display(int i);      // slot that will display the integer passed as a parameter
 +};
 +</​file>​
 +The implementation of such components will not be a problem and will unfold quite naturally.
 +<file cpp sample.cpp>​
 +#include "​sample.h"​ // header declaring components
 +#include <​iostream>​
 +
 +void Loop::​setIterations(int n)
 +{
 +    for (int i=0; i < n; i++) 
 +    {
 +      std::cout << "​[Loop] Emitting iteration " << i << std::endl;
 +      emit newIteration(i);​ // emit trigger the corresponding signal
 +    }
 +    emit sendToken("​end"​);​
 +}
 +
 +void DisplayInt::​display(int i)
 +{
 +  std::cout << "​[DInt] Received integer " << i << std::endl;
 +}
 +</​file>​
 +
 +===== Embedding components into a library =====
 +Once components are created, the library will be easy to make. 
 +You will have to run once the executable ''​arcslibmaker''​
 +(you may find more information on [[http://​arcs.ibisc.univ-evry.fr/​doc/​arcslibmaker.html|arcslibmaker manpage]]).
 +If files were in a folder named ''​sample'',​ ''​arcslibmaker''​
 +will create a Qt project file named ''​sample.pro''​ that includes
 +source files as well as special directives in order to compile the component library.
 +Moreover, a file named ''​libsample.alx''​ will be generated and you will have to 
 +edit it. If necessary, you can also edit the project file (in this case, you may refer to 
 +the complete documentation of the [[http://​qt-project.org/​doc/​qt-5.1/​qtdoc/​qmake-manual.html|qmake tool]]).
 +<hidden click to display project file contents ''​sample.pro''>​
 +<code bash>
 +win32-msvc* {
 +   ​TEMPLATE = vclib
 + } else {
 +   ​TEMPLATE = lib
 +}
 +INCLUDEPATH += $$(ARCSDIR)/​include
 +LIBS += -L$$(ARCSDIR)/​lib -larcs
 +CONFIG += dll
 +QT = core
 +
 +# source files to compile
 +HEADERS += sample.h
 +SOURCES += sample.cpp
 +
 +# ARCS specific rules
 +ALXFILE = libsample.alx
 +OTHER_FILES += libsample.alx
 +arcslibrary.output = alm_${QMAKE_FILE_BASE}.cpp
 +arcslibrary.input = ALXFILE
 +arcslibrary.commands = arcslibmaker ${QMAKE_FILE_NAME}
 +arcslibrary.variable_out = SOURCES
 +QMAKE_EXTRA_COMPILERS += arcslibrary
 +</​code>​
 +</​hidden>​
 +
 +First, we will have a look at the file ''​libsample.alx''​ which is a XML formatted document
 +describing with a few markups component libraries. In this file, two sections will be of 
 +interest:
 +  * the ''​headers''​ section, where we will put which header files are declaring components;
 +  * the ''​components''​ section, where we will tell the actual components that the library will store.
 +Our library contains two components of types **Loop** and **DisplayInt** declared in a header file named
 +''​sample.h''​. Therefore, our file ''​libsample.alx''​ should be edited as follows:
 +<file xml libsample.alx>​
 +<​library>​
 +  <​headers>​
 +    <header name="​sample.h"/>​
 +  </​headers>​
 +  <​components>​
 +    <​component name="​Loop"/>​
 +    <​component name="​DisplayInt"/>​
 +  </​components>​
 +</​library>​
 +</​file>​
 +
 +Thanks to the rules automatically put in the project file, the utility ''​arcslibmaker''​ will be able to parse the file
 +''​libsample.alx''​ and generate C++ wrappers for the component library in a file named ''​alm_libsample.cpp''​.
 +<hidden Click here to display ''​alm_libsample.cpp''>​
 +<code cpp>
 +#​include<​arcs/​arcslibtoolkit.h>​
 +#​include<​QMetaType>​
 +#​include<​sample.h>​
 +
 +extern "​C"​ DLL_EXPORT void arcsLibraryRegister(ARCSComponentMap* cmap, ARCSFamilyMap* , ARCSTypeMap* )
 +{
 +  cmap->​insert("​Loop",​new ARCSNativeComponentTemplate<​Loop>​());​
 +  cmap->​insert("​DisplayInt",​new ARCSNativeComponentTemplate<​DisplayInt>​());​
 +}
 +
 +extern "​C"​ DLL_EXPORT void arcsLibraryUnregister(ARCSComponentMap* cmap, ARCSFamilyMap* , ARCSTypeMap* )
 +{
 +  delete cmap->​take("​Loop"​);​
 +  delete cmap->​take("​DisplayInt"​);​
 +}
 +</​code>​
 +</​hidden>​
 +===== Compiling the library =====
 +One call to ''​qmake''​ will generate the appropriate ''​Makefile''​ (or MS Visual studio projects). You will then be able
 +to call ''​make''​ in order to compile the library. ​
 +
 +===== The complete workflow =====
 +To sum it up, the complete workflow is as follows:
 +  - prepare component source files;
 +  - launch ''​arcslibmaker'';​
 +  - edit XML files that were produced by ''​arcslibmaker''​ in order to tell what are the components;
 +  - launch ''​qmake''​ to generate a ''​Makefile''​ under Unix like systems;
 +  - compile the library using ''​make''​.
 +