Reference Types

About

Interfaces in the MAXON API ALIASES can be "virtual" or "non-virtual" interfaces. Such interfaces can be registered using different reference types. These reference types define how the created reference classes are build and how they behave.

Note
"Virtual" interfaces should be preferred.

Interface Reference Types

These reference types are applicable to virtual and non-virtual interfaces:

Note
Virtual interface instances always use reference counting.

CONST

An interface using MAXON_REFERENCE_CONST only adds const functions to the created reference class. To create instances of such a read-only object a helper interface might be used that is able to create different objects (see also Factories).

The declaration of the const interface and the helper interface could look like this:

// This example shows an interface which uses MAXON_REFERENCE_CONST
// so only const functions are added to the reference class.
// ---------------------------------------------------------------------
// A custom unique ID class.
// ---------------------------------------------------------------------
class CustomUniqueIdInterface : MAXON_INTERFACE_BASES(maxon::ObjectInterface)
{
MAXON_INTERFACE(CustomUniqueIdInterface, MAXON_REFERENCE_CONST, "net.maxonexample.interfaces.uniqueid");
public:
// ---------------------------------------------------------------------
// Returns the internal unique ID.
// ---------------------------------------------------------------------
MAXON_METHOD maxon::UInt GetId() const;
};
// forward declaration of the reference class
// const classes do not use the suffix "Ref"
class CustomUniqueId;
// ---------------------------------------------------------------------
// Non-virtual interface as a CustomUniqueId generator.
// ---------------------------------------------------------------------
class CustomUniqueIdGenerator
{
MAXON_INTERFACE_NONVIRTUAL(CustomUniqueIdGenerator, MAXON_REFERENCE_NONE, "net.maxonexample.interfaces.uniqueidgenerator");
public:
// ---------------------------------------------------------------------
// Returns a new CustomUniqueId or an error.
// ---------------------------------------------------------------------
};

The implementation of the const class can look like this. Notice the Init() function that takes an argument:

// This example shows an implementation of a const interface.
// The only way to modify the internally stored data is on creation with Init().
// implementation of CustomUniqueIdInterface
class UniqueIdImp : public maxon::Component<UniqueIdImp, CustomUniqueIdInterface>
{
public:
{
_id = id;
return maxon::OK;
}
MAXON_METHOD maxon::UInt GetId() const { return _id; }
private:
};

The implementation of the helper interface creates a new object by creating a new instance of the component. Calling CreateInit() will invoke the above Init() function.

// This example shows the implementation of a static non-virtual interface function.
// This function can access an implementation class (UniqueIdImp) to create a new instance.
maxon::Result<CustomUniqueId> UniqueIdGeneratorImpl::GetUniqueID()
{
// increment global ID
g_uniqueIDs++;
// create new UniqueId
return UniqueIdImp::CreateInit(g_uniqueIDs);
}

Now one can use the helper interface to create a new instance of the read-only const interface.

// This example creates a new CustomUniqueId object using a static function of a helper interface.
// create ID
const CustomUniqueId id = CustomUniqueIdGenerator::GetUniqueID() iferr_return;
// use ID
const maxon::UInt value = id.GetId();
DiagnosticOutput("UID: @", value);

COPY_ON_WRITE

If an object of a copy-on-write class is copied, it will not copy its content. It will only store a reference to the original object. Only if the copy or original object are changed, data is copied.

A simple copy-on-write interface can look like this:

// This example shows a simple interface of the reference type MAXON_REFERENCE_COPY_ON_WRITE.
// ---------------------------------------------------------------------
// Class to store an array of maxon::Float values.
// ---------------------------------------------------------------------
class FloatArrayInterface : MAXON_INTERFACE_BASES(maxon::ObjectInterface)
{
MAXON_INTERFACE(FloatArrayInterface, MAXON_REFERENCE_COPY_ON_WRITE, "net.maxonexample.interfaces.floatarray");
public:
// ---------------------------------------------------------------------
// Adds the given value to the array.
// ---------------------------------------------------------------------
};

The implementation is straightforward:

// This example shows an implementation of a copy-on-write interface.
// implementation of FloatArrayInterface
class FloatArrayImpl : public maxon::Component<FloatArrayImpl, FloatArrayInterface>
{
public:
// implementation of an interface function
{
return _data.Append(value);
}
// implementation of maxon::ComponentRoot::CopyFrom()
maxon::Result<void> CopyFrom(const FloatArrayImpl& arr)
{
return _data.CopyFrom(arr._data);
}
// implementation of maxon::ObjectInterface::ToString()
{
maxon::String result { "Values: " };
for (const maxon::Float v : _data)
result += maxon::String::FloatToString(v) + ", "_s;
return result;
}
private:
};

The reference class of a copy-on-write interface does not use the usual "Ref" suffix. It can be used as usual:

// This example creates and uses copy-on-write objects.
// create original
FloatArray original = componentClass.Create() iferr_return;
// use original
original.AddValue(1.0) iferr_return;
original.AddValue(2.0) iferr_return;
// create copy
FloatArray copy = componentClass.Create() iferr_return;
// data is assigned but not yet copied
copy = original;
// original and copy have access to the same data
DiagnosticOutput("Original: @", original);
DiagnosticOutput("Copy: @", copy);
// add further data; internal data will now be copied
copy.AddValue(3.0) iferr_return;
// original and copy now access different data
DiagnosticOutput("Original: @", original);
DiagnosticOutput("Copy: @", copy);

Non-Virtual Interface Reference Types

These reference types are only applicable to non-virtual interfaces:

NONE

Non-virtual interfaces can use the reference type MAXON_REFERENCE_NONE. This will create a static reference class.

The non-virtual interface is declared like this:

// This example shows a simple non-virtual interface of the reference type MAXON_REFERENCE_NONE.
// ---------------------------------------------------------------------
// Class to roll a dice.
// ---------------------------------------------------------------------
class DiceInterface
{
MAXON_INTERFACE_NONVIRTUAL(DiceInterface, MAXON_REFERENCE_NONE, "net.maxonexample.interfaces.dice");
public:
// ---------------------------------------------------------------------
// Rolls the dice and returns a random number.
// ---------------------------------------------------------------------
static MAXON_METHOD maxon::UInt RollDice();
};

The implementation can look like this:

// This example shows the implementation of a simple interface.
// implementation of DiceInterface
class DiceInterfaceImpl : protected DiceInterface
{
MAXON_IMPLEMENTATION(DiceInterfaceImpl)
public:
static maxon::UInt RollDice();
};
// implementation of DiceInterface::RollDice()
maxon::UInt DiceInterfaceImpl::RollDice()
{
// chosen by fair dice roll.
// guaranteed to be random.
return 4;
}
MAXON_IMPLEMENTATION_REGISTER(DiceInterfaceImpl);

The static reference class is used this way:

// This example uses the static member function of the interface.
const maxon::UInt randomNumber = DiceInterface::RollDice();
DiagnosticOutput("Number: @", randomNumber);

Further Reading

maxon::ComponentWithBase
Definition: objectbase.h:2604
maxon
The maxon namespace contains all declarations of the MAXON API.
Definition: c4d_basedocument.h:15
MAXON_INTERFACE_BASES
#define MAXON_INTERFACE_BASES(...)
Definition: objectbase.h:1038
MAXON_IMPLEMENTATION_REGISTER
#define MAXON_IMPLEMENTATION_REGISTER(C,...)
Definition: interfacebase.h:1426
MAXON_COMPONENT
#define MAXON_COMPONENT(KIND,...)
Definition: objectbase.h:2166
maxon::String
Definition: string.h:1213
maxon::OK
return OK
Definition: apibase.h:2546
iferr_return
#define iferr_return
Definition: resultbase.h:1465
maxon::Float
Float64 Float
Definition: apibase.h:195
maxon::BaseArray
Definition: basearray.h:366
DiagnosticOutput
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:167
maxon::Result
Definition: apibase.h:316
MAXON_METHOD
#define MAXON_METHOD
Definition: interfacebase.h:877
maxon::ToString
String ToString(const String &str, const FormatStatement *formatStatement, Bool=false)
Definition: string.h:1696
MAXON_IMPLEMENTATION
#define MAXON_IMPLEMENTATION(C)
Definition: interfacebase.h:1322
MAXON_INTERFACE_NONVIRTUAL
#define MAXON_INTERFACE_NONVIRTUAL(Name, REFKIND, ID)
Definition: interfacebase.h:1192
MAXON_REFERENCE_CONST
#define MAXON_REFERENCE_CONST(FREEIMPL)
Definition: interfacebase.h:1049
MAXON_INTERFACE
#define MAXON_INTERFACE(Name, REFKIND, ID)
Definition: objectbase.h:1109
maxon::FormatStatement
Class to store formatting statements.
Definition: string.h:1981
MAXON_REFERENCE_NONE
#define MAXON_REFERENCE_NONE(FREEIMPL)
Definition: interfacebase.h:908
maxon::ResultOk< void >
Definition: resultbase.h:192
maxon::UInt
UInt64 UInt
unsigned 32/64 bit int, size depends on the platform
Definition: apibase.h:187
UInt
maxon::UInt UInt
Definition: ge_sys_math.h:65
MAXON_REFERENCE_COPY_ON_WRITE
#define MAXON_REFERENCE_COPY_ON_WRITE(FREEIMPL)
Definition: interfacebase.h:1066