Skip to content

Module Tutorial

knicos edited this page Apr 7, 2013 · 14 revisions

Cadence supports the dynamic loading of custom modules written in C++. Typically these are used in one of the following ways:

  • To add new agency which responds to events and observes/modifies the Cadence graph. An example would be a new user interface for Cadence or a new hardware device providing IO to Cadence.
  • Add new event handlers to provide an alternative internal storage of the graph or virtual parts of the graph such as special arithmetic operators or remote storage.
  • Add a new scripting language to replace or work above DASM.

Contents

Template Module Code

A basic module must implement the functions shown in the example below.

extern "C" void initialise(const cadence::core::OID &base) {
}

extern "C" void cadence_update() {
}

extern "C" void finalise() {
}

The initialise function is called when the module is loaded and is passed an OID corresponding to the base object that this module is associated with. The base object can be chosen in the script that loads the module.

cadence_update is optional and optionally called at a specified frequency or as often as possible. Typically it would be used for polling or maintenance operations that don't correspond to events in Cadence.

Finalise is called when the module is unloaded, usually when Cadence itself is terminated.

A module must be compiled as a shared library (--shared -fPIC) and linked with the libcadence-embedded library. Finally, a DASM script should be used for loading and configuring a module, an example is given below.

.my_base = (new
);

.modules my_module = (new type=Module
	file = (new type=LocalFile
		filename = "libcadence_mymodule.so"
	)
	base = (.my_base)
	update = false
	frequency = 0.00
);

Unless using an absolute path Cadence will look in @PREFIX@/share/cadence-embedded/modules, the current directory and the systems library folders for the module so file. If installing the module it is best to install to the cadence-embedded/modules folder. Note: @PREFIX@ usually defaults to /usr/local but can be customised using ./configure --prefix="..." during the build process.

Agent Module

An agent module will provide one or more classes that inherit the cadence::Agent class. The new classes are then registered with Cadence so that they can be constructed, destroyed and notified of any events as appropriate. An instance of one of these agent classes can be associated with a particular cadence OID in order to respond to changes to that (or other) objects and observe/modify the object.

Header Example

#ifndef _CADENCE_CANVU_BACKLIGHT_H_
#define _CADENCE_CANVU_BACKLIGHT_H_

#include <cadence-embedded/agent.h>

class CANvuBacklight : public cadence::Agent {
	public:
	OBJECT(Agent, CANvuBacklight);

	CANvuBacklight(const cadence::core::OID &);
	~CANvuBacklight();

	PROPERTY_RF(int, lcd, "lcd");
	PROPERTY_WF(int, lcd, "lcd");

	BEGIN_EVENTS(Agent);
	EVENT(evt_lcd, (*this)("lcd"));
	END_EVENTS;
};

#endif

This header defines a new agent class called CANvuBacklight which has a property called lcd. The PROPERTY_RF and PROPERTY_WF macros define accessor methods that get or set the "lcd" property in Cadence. These are equivalent to using get("lcd") and set("lcd",...) but can be used as lcd() and lcd(...) respectively.

The event macros allow specified C++ methods to be called when a specified property is changed. In this case the evt_lcd method is called whenever the local "lcd" property changes.

Note the OBJECT macro at the top, before the constructor, which must be included with first argument as the base class and the second as the name of the new agent class.

Main source example:

#include <cadence-embedded/agent.h>
#include <cadence-embedded/cadence.h>
#include <canvu-vm/backlight.h>

using namespace cadence;
using namespace cadence::core;
using namespace canvu;

CANvuBacklight::CANvuBacklight(const OID &obj) : Agent(obj) {
	registerEvents();
}

CANvuBacklight::~CANvuBacklight() {
}

namespace canvu {
	OnEvent(CANvuBacklight, evt_lcd) {
		int level = lcd();
		...
	}
};

IMPLEMENT_EVENTS(CANvuBacklight,Agent);


extern "C" void initialise(const cadence::core::OID &base) {
	Object::registerType<CANvuBacklight>();
	(Object*)base;
}
Clone this wiki locally