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
QObjects
with
specific signals and slots.
We will document the steps needed to produce a library like the sample
one.
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:
#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 };
The implementation of such components will not be a problem and will unfold quite naturally.
#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; }
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 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 qmake tool).
click to display project file contents sample.pro
click to display project file contents sample.pro
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
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:
headers
section, where we will put which header files are declaring components;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:
<library> <headers> <header name="sample.h"/> </headers> <components> <component name="Loop"/> <component name="DisplayInt"/> </components> </library>
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
.
Click here to display alm_libsample.cpp
Click here to display alm_libsample.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"); }
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.
To sum it up, the complete workflow is as follows:
arcslibmaker
;arcslibmaker
in order to tell what are the components;qmake
to generate a Makefile
under Unix like systems;make
.