Interface Implementation

About

An interface declares an empty virtual class. The actual functionality must be defined in an implementation. For a given interface multiple implementations can exist. Such an implementation is called a component.

An implementation can be defined in any source code file of a module/plugin. This way it is possible to publish the interface header file and to keep the implementation private.

Implementation

A simple interface is defined as:

A simple implementation of that interface can look like this:

// This example shows the implementation of a simple interface.
// This class implements SimpleClassInterface.
class SimpleClassImplementation : public maxon::Component<SimpleClassImplementation, SimpleClassInterface>
{
public:
// implementation of interface methods
MAXON_METHOD void SetNumber(maxon::Int number)
{
_value = number;
}
MAXON_METHOD maxon::Int GetNumber() const
{
return _value;
}
// private data only available inside the implementation
private:
maxon::Int _value = 1;
};
Definition: objectbase.h:2694
Int64 Int
signed 32/64 bit int, size depends on the platform
Definition: apibase.h:196
#define MAXON_COMPONENT(KIND,...)
Definition: objectbase.h:2234
#define MAXON_METHOD
Definition: interfacebase.h:1020
  • The attribute maxon::Component defines the interface this component implements. A component can also use code defined in a base component. See Component Bases for more details.
  • The attribute MAXON_COMPONENT() declares the class as a component and adds additional code if needed.
  • The component implements the virtual functions of the interface that are declared with MAXON_METHOD.
  • Class members can only exist in the implementation class.

Register

A new component must be registered to inform Cinema 4D about it. The registration defines the ID which can be used to access the component class which in return can be used to create instances. The ID is created by combining the reverse domain name and the implementation class name.

Note
If it should be possible that another interface inherits from a custom interface it is needed that one or many implementations of that interface are accessible (e.g. as published object using MAXON_COMPONENT_CLASS_REGISTER). See Interface Inheritance.
// This example registers the component using the base identifier
// and the implementation class name.
MAXON_COMPONENT_CLASS_REGISTER(SimpleClassImplementation, "net.maxonexample.class.somesimpleclass");
#define MAXON_COMPONENT_CLASS_REGISTER(C,...)
Definition: objectbase.h:2432

It is also possible to expose a given component as a published object that was declared with MAXON_DECLARATION:

// This example registers the component and publishes it as the published object "SomeSimpleClass".
// The published object must be declared in a header file.
MAXON_COMPONENT_CLASS_REGISTER(OtherClassImplementation, SomeSimpleClass);

This published object is used like this:

// This example creates a reference class from a component
// registered at the given declaration.
// create reference
// The "SomeSimpleClass" published object is declared in a header file.
// The obtained component is used to create a new instance using Create().
const SimpleClassRef simpleClass = SomeSimpleClass().Create() iferr_return;
// use reference
simpleClass.SetNumber(456);
const maxon::Int number = simpleClass.GetNumber();
DiagnosticOutput("Number: @", number);
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:170
#define iferr_return
Definition: resultbase.h:1771

MAXON_COMPONENT_OBJECT_REGISTER is used to create an instance of the component class and to publish that object:

// This example registers the given implementation, creates an instance of the class
// and makes that object available with the given published object "OtherSimpleClass".
MAXON_COMPONENT_OBJECT_REGISTER(ThirdSimpleClassImplementation, OtherSimpleClass);
#define MAXON_COMPONENT_OBJECT_REGISTER(C,...)
Definition: objectbase.h:2495

The object published this way can be obtained like this:

// This example shows how to access an object created
// and registered with MAXON_COMPONENT_OBJECT_REGISTER.
{
// access object crated with MAXON_COMPONENT_OBJECT_REGISTER
const SimpleClassRef& simpleClass = OtherSimpleClass();
const maxon::Int number = simpleClass.GetNumber();
DiagnosticOutput("Number: @", number);
}
{
// create copy of the object created with MAXON_COMPONENT_OBJECT_REGISTER
const SimpleClassRef simpleClass = OtherSimpleClass();
// use reference
simpleClass.SetNumber(789);
const maxon::Int number = simpleClass.GetNumber();
DiagnosticOutput("Number: @", number);
}
#define MAXON_SCOPE
Definition: apibase.h:3071

Multiple Components

The attribute MAXON_COMPONENT() declares a given class as a component. The attribute can be used to define the component type:

Additionally, MAXON_COMPONENT() can define additional components that are added to a given component. If this is not sufficient one can implement maxon::ComponentRoot::ConfigureClass(). These additional components typically implement the interface's base interfaces. See Interface Inheritance.

Default Functions

Every component can implement these default functions. They are declared in the maxon::ComponentRoot class.

  • maxon::ComponentRoot::InitImplementation(): Is called when the component is loaded (Cinema 4D startup).
  • maxon::ComponentRoot::FreeImplementation(): Is called when the component is unloaded (Cinema 4D shutdown).
  • maxon::ComponentRoot::InitComponent(): Is called when an instance of the component is created.
  • maxon::ComponentRoot::FreeComponent(): Is called when an instance of the component is destroyed.
  • maxon::ComponentRoot::CopyFrom(): Is needed if a component has data members and to support maxon::ObjectInterface::CopyFrom() and maxon::ObjectInterface::Clone().
  • maxon::ComponentRoot::DescribeIO(): Is needed to describe how data members must be written to disc. See DescribeIO Manual.
  • maxon::ComponentRoot::ConfigureClass(): Is called to add additional components.
Note
InitImplementation() is called before the Cinema 4D core is loaded. This means that no Cinema API code can be called in this context.

Static Methods

Static methods of interfaces can only be implemented once. The implementation class of these methods must be additionally registered with MAXON_STATIC_REGISTER().

Further Reading