FreeElectron
Component Writer's Guide

Purpose

This document should describes how to make your own components and package them into a library.

Component

Each component has to be virtually derived from fe::Component, but not neccessarily directly. Since components are instantiated through automatically generated factories, all component implementation classes should have a single constructor with no arguments.

Any component can participate in a post-constructor mechanism. This allows all participating classes in the the class hierarchy to have their initialize methods called in the same order as the original construction. Post-construction is useful for constructive operations that cannot be done safely or appropriately during real construction. See fe::Initialized for details.

All components can be used in smart pointers (fe::sp), smart handles (fe::hp), copy-on-write pointers (fe::cp), and smart hubs (fe::Component::adjoin).

Interfaces and Implementations

The plugin system does not require an interface/implementation design paradigm. However, it does promote and facilitate its use.

This is how you can use interfaces in the context of this framework.

Interfaces are abstract classes. They contain a set of public virtual functions that state what implementions fulfilling that interface can do. Generally, interfaces are always virtually inherited to prevent redundant base classes.

An implememention defines actual code for any number of interfaces. Under normal conditions, implementations should only be accessed through their interfaces.

Implementations can inherit from other implementions to extend or reuse existing code, even across multiple dynamic libraries. They generally inherit non-virtually since it is more efficient.

Inherited implementations have more intimate access to the base classes than would normally be available through just the interfaces. It is basically the same design responsibility that exists in normal class inheritance.

Dirty interfaces are deviations that contain state in the interface. They are frowned upon, but there is no mechanism to prevent them.

Component Naming

The string names for components are expected to follow a specific dot-based convention of the form "InterfaceI.Implementation.origin.misc".

By convention, the first token exactly states a C++ interface class that the component fulfills. A component can register as multiple interfaces if it would like to make itself explicitly available to fulfill all those interfaces. A component is not required to register for all interfaces that it could potentially fulfill.

The second token exactly states the C++ class that is explicitly instantiated for this name.

The third token states who is providing the interface, presumably a organization or company name.

The fourth token is basically anything that follows, perhaps a description or notice. It shouldn't be expected, and it probably shouldn't ever be matched against.

Requests for component creation are usually abbreviated. If a request string matches a candidate exactly up to where the terminator in the request aligns with a period in the candidate, the pair is considered a match.

For example, a request for "WindowI" can be resolved with "WindowI.NativeWindow.fe".

An asterisk between two periods matches anything in that token. Using the same example, "WindowI.*.fe" matches "WindowI.NativeWindow.fe" or "WindowI.SpecialWindow.fe", but not "WindowI.NativeWindow.substitute".

Complex regular expression matching is not supported in this context.

Library Packaging

A set of closely related components are grouped into a module. Each of these modules is compiled into a dynamic library. Each "DL" is represented as a shared object (.so) under Linux or a DLL (.dll) under Win32.

By convention, each module should include a moduleDL.cc file as described in fe::Library.