charon-core  0.3.1
Using charon-core

Charon-core is a library, so don't look for some kind of main executable.

You can use charon-core in your own projects, use the classes and frameworks that are offered here. A sample data-processing framework that uses the ParameteredObject class can be found in the imgmanip directory. The file test/parametertest.cpp and test/imgmaniptest.cpp show how to use it.

Implementing a parametered Object

Here, we discuss the content of the source file paramObjSample.cpp in the examples directory.

#include <iostream>
#include <cstdlib>
class Sample : public ParameteredObject {
Obviously, the new class needs to inherit from ParameteredObject to get all the features defined there.

public:
InputSlot<float> in2; ///< sample float input slot
Here we define the parameters that we want to use to store the object properties. These properties can be stored by ParameteredObject::saveParameters(), which only saves the parameters and ParameteredObject::save() which also stored the slot connections. The parameters can be loaded by ParameteredObject::loadParameters(). Like ParameteredObject::saveParameters(), this doesn't touch the slots. We also define input and output slots that can be used for data exchange between objects.

Sample(const std::string& name = "") :
ParameteredObject("sample", name, "some sample class"),
par1(20), // initial values ...
par2(1.5), // ... for parameters ...
out1(8), // ... and for output ...
out2(7.3f), // ... slots
in2(true, true) // make in2 optional and multislot
{
// parameters
ParameteredObject::_addParameter (par1, "par1", "sample integer parameter");
ParameteredObject::_addParameter (par2, "par2", "sample float parameter");
// slots
ParameteredObject::_addInputSlot (in1, "in1", "sample integer input slot");
ParameteredObject::_addInputSlot (in2, "in2", "sample float input slot");
ParameteredObject::_addOutputSlot(out1, "out1", "sample integer output slot");
ParameteredObject::_addOutputSlot(out2, "out2", "sample float output slot");
}
};
In the constructor, we have to call the inherited constructor of ParameteredObject. There, we have to specify an unique class name and pass the instance name. Then we have to initialize the parameters and output slots. Input slot in2 is initialized as optional multislot. The effects are described below. Within the constructor, we have to add all parameters and slots to the corresponding management lists. This is done by calls of the following functions:

This can also be delegated to some init() function if there are more than one constructor. The parameters of the _addXX functions are described in the API documentation.

class Outputgen : public ParameteredObject {
public:
Outputgen(const std::string& name = "") :
ParameteredObject("outputgen", name,
"class to generate int and float output"),
out1(10), // set initial values
out2(5.5f) // ------- " --------
{
ParameteredObject::_addOutputSlot(out1, "out1", "integer output slot");
ParameteredObject::_addOutputSlot(out2, "out2", "float output slot");
}
};
The second example class is declared similarly.

int main() {
ParameterFile testfile;
Sample* sample = new Sample;
// sample->par1 is 20
sample->par1 = 5;
// now, sample->par1 == 5
sample->saveParameters(testfile);
// set new value
sample->par1 = 10;
// load old one
sample->loadParameters(testfile);
sout << "par1: " << sample->par1 << std::endl; // value is now 5.
Object creation and access of the parameters is quite easy. The save/load routines handle all registered parameters.

// parametered object connections
Outputgen* outgen = new Outputgen;
Outputgen* outgen2 = new Outputgen;
outgen->out1.connect(sample->in1);
// slot in2 needs not to be connected because it's optional
// try to connect multiple sources to in2
outgen->out2.connect(sample->in2);
outgen2->out2.connect(sample->in2);
// outgen and sample are now in a connected component of 3 objects
// outgen only has one neighbour, sample2
// sample has two neighbours, outputgen and outgen2
Here you can see how objects can be connected with each other.

// save object and connections
testfile.clear();
sample->save(testfile);
outgen->save(testfile);
outgen2->save(testfile);
The object connections are also saved by the ParameteredObject::save() routine. The slot data will not be stored.

// delete connected object
// connection should be removed (also from outgen)
delete sample;
assert(!outgen->out1.connected());
assert(!outgen->out2.connected());
// cleanup
delete outgen;
delete outgen2;
We do the cleanup and make sure that the destructor automatically disconnects existing slot connections.

testfile.save("example.wrp");
return EXIT_SUCCESS;
}
At the end, we save the ParameterFile to the disk.

Dynamic Modules

It is possible to write Modules where the number or kind of Parameters and Slots is not fix in any configuration. Such modules, where this parameter/slot interface depends on its configuration (i.e., in the most general case, it depends on the workflow configuration parameter file) are called dynamic Modules.

For writing such dynamic modules, you have to call the function ParameteredObject::_setDynamic() within the constructor to set up the module metadata such that other tools know, that the module interface has to be queried providing the current configuration.

The next step is to reimplement the virtual function ParameteredObject::prepareDynamicInterface(const ParameterFile&) where the current configuration is provided as a parameter file. Within this function, the information from the parameter file may be used to determine, which parameters and slots to set up. Definition/registration of these parameter/slots is done there as usual. Do not forget to call the following routines for registration:

Other tools and frameworks in charon-core

The most important framework in charon-core is the ParameteredObject framework mentioned above. But there are even more nice features. These features are easy to understand so the API documentation should be sufficient:

  • class FileTool:
    platform independent file manipulations
  • class ParameterFile:
    parameter file handling used by parametered objects etc.
  • class SplitStream:
    highly customizable output stream class with possibility to stream into different targets etc.
  • class StringTool:
    string manipulations
  • class TypeDetector:
    guessing of basic data types