Entity Creation

About

To utilize features of the MAXON API it is typically needed to allocate an object that provides access to data and functions. These objects can either be simple C++ structures and classes or reference classes representing implementations of interfaces.

Object Creation

Simple objects can be allocated using the following memory management tools of the MAXON API. If it is necessary to allocate objects directly, these functions should always be used instead of the standard C++ allocators.

  • NewObj(): Creates an object of the given type with the given parameters. For handling the returned error see Error Handling.
  • DeleteObj(): Deletes the given object.
Note
If possible, one should always use reference counting. See References.

For allocation of low-level memory see Memory Allocation.

// This example shows a C++ custom class.
//----------------------------------------------------------------------------------------
// A simple class storing an integer value.
//----------------------------------------------------------------------------------------
class ExampleClass
{
public:
//----------------------------------------------------------------------------------------
// Constructor.
// @param[in] number The number to store.
//----------------------------------------------------------------------------------------
MAXON_IMPLICIT ExampleClass(maxon::Int number)
{
_number = number;
}
//----------------------------------------------------------------------------------------
// Constructor. The internal number is set to 0.
//----------------------------------------------------------------------------------------
MAXON_IMPLICIT ExampleClass()
{
_number = 0;
}
//----------------------------------------------------------------------------------------
// Returns the stored number.
// @return The number.
//----------------------------------------------------------------------------------------
maxon::Int GetNumber()
{
return _number;
}
//----------------------------------------------------------------------------------------
// Sets the stored number.
// @param[in] number The number to store.
//----------------------------------------------------------------------------------------
void SetNumber(maxon::Int number)
{
_number = number;
}
private:
maxon::Int _number;
};
// This example creates a new instance of the example class using NewObj().
// create the new object
ExampleClass* exampleObject = NewObj(ExampleClass, 100) iferr_return;
// use the object
const maxon::Int number = exampleObject->GetNumber();
DiagnosticOutput("Number: @", number);
// delete the object
DeleteObj(exampleObject);

Most complex classes of the MAXON API provide a (static) "Create()" function that can be used to create new instances. It is recommended to add such a "Create()" function also to a custom class if it must be initialized after creation.

// This example shows a simple class that provides a static Create() function.
// This Create() function allocates a new instances and initializes it. Only if
// the creation and initialization were successful, a new object is returned.
//----------------------------------------------------------------------------------------
// Class to store an array of ascending integer numbers.
//----------------------------------------------------------------------------------------
class AscendingNumbers
{
private:
//----------------------------------------------------------------------------------------
// Inits the array with elements defined by the given range.
// @param[in] start The minimum value.
// @param[in] end The maximum value.
// @return maxon::OK on success.
//----------------------------------------------------------------------------------------
{
// clear array
_numbers.Flush();
if (end < start)
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
// fill array with ascending integer values
for (maxon::Int i = start; i <= end; i++)
{
_numbers.Append(i) iferr_return;
}
return maxon::OK;
}
private:
public:
//----------------------------------------------------------------------------------------
// Static function to create a new AscendingNumbers instance.
// @param[in] start The minimum value.
// @param[in] end The maximum value.
// @return The new AscendingNumbers instance. The caller owns the object.
//----------------------------------------------------------------------------------------
{
// create object
AscendingNumbers* const numbers = NewObj(AscendingNumbers) iferr_return;
// take ownership to ensure memory clean-up in case of an error
using AscendingNumbersRef = maxon::UniqueRef<AscendingNumbers>;
AscendingNumbersRef ref(numbers);
// init array
numbers->Init(start, end) iferr_return;
// release and return
return ref.Disconnect();
}
//----------------------------------------------------------------------------------------
// Returns the number of stored elements.
// @return The number of stored elements.
//----------------------------------------------------------------------------------------
{
return _numbers.GetCount();
}
//----------------------------------------------------------------------------------------
// Returns the number at the given index.
// @param[in] index The index position of the number to access.
// @return The number at the given index.
//----------------------------------------------------------------------------------------
{
// range check
const maxon::Bool undershoot = index < 0;
const maxon::Bool overshoot = index >= _numbers.GetCount();
if (undershoot || overshoot)
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
return _numbers[index];
}
//----------------------------------------------------------------------------------------
// Copies the data of the given AscendingNumbers object. Will delete all previously stored data.
// @param[in] src Source AscendingNumbers-object to copy from.
// @return maxon::OK on success.
//----------------------------------------------------------------------------------------
maxon::Result<void> CopyFrom(const AscendingNumbers& src)
{
return _numbers.CopyFrom(src._numbers);
}
};
// This example shows how to use the static Create() function to allocate a new instance.
// create new instance
AscendingNumbers* const numbers = AscendingNumbers::Create(10, 20) iferr_return;
// defining a StrongRef alias to store the new instance
using AscendingNumbersRef = maxon::StrongRef<AscendingNumbers>;
// reference takes ownership to ensure memory clean-up
AscendingNumbersRef ref(numbers);
// use object
const maxon::Int count = numbers->GetCount();
for (maxon::Int i = 0; i < count; ++i)
{
const maxon::Int number = numbers->GetNumber(i) iferr_return;
DiagnosticOutput("Number @", number);
}

Interface References

A reference object represents an implementation of a given interface. Such a reference object can be created in various ways. For details see Interface Basics and Using Interfaces.

Note
References to interfaces with only one implementation can often be allocated on the stack e.g. maxon::String.

This example shows how a reference class instance is created using the maxon::Id of the specific implementation:

// This example creates an instance of an interface
// and uses the created instance.
// define the ID of the component to use
const maxon::Id id { "net.maxonexample.class.somesimpleclass" };
// get component class of the given ID from the global maxon::Classes registry
const maxon::Class<SimpleClassRef>& componentClass = maxon::Classes::Get<SimpleClassRef>(id);
// create reference
const SimpleClassRef simpleClass = componentClass.Create() iferr_return;
// use reference
simpleClass.SetNumber(123);
const maxon::Int number = simpleClass.GetNumber();
DiagnosticOutput("Number: @", number);

This example shows how to obtain a reference class from an implementation that is presented as a published object. See Published Objects Usage.

// 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);

Interface implementations can also be registered at registries. From these registries the reference class is obtained using the specific maxon::Id of the registered implementation. See Registry Usage.

// This example creates a reference object from the registry with the given ID.
// get the class with the given Id from the registry "ColorClasses"
const maxon::Id redID { "net.maxonexample.class.colors.red" };
const maxon::Class<ColorRef>* const componentClass = ColorClasses::Find(redID);
if (componentClass == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not get color."_s);
// create reference object
const ColorRef color = componentClass->Create() iferr_return;
// use reference object
const maxon::String colorName = color.GetName();
const maxon::Color32 colorRGB = color.GetRGB();
DiagnosticOutput("Color Name: @", colorName);
DiagnosticOutput("Color RGB: @", colorRGB);

Interfaces support inheritance. This means a given reference object of a base class can be cast into the reference class of a derived interface. If the cast is not possible a nullptr is returned.

  • maxon::Cast(): Casts the object into the given interface type.
  • maxon::AssertCast(): Casts the object into the given interface type. Checks only, if the object is really an instance of the interface in debug mode.
// This example accesses an error and casts it into a maxon::ErrnoError to get the stored error code.
// perform task
const maxon::Result<void> res = PerformTaskCheckError();
// check for failure
if (res == maxon::FAILED)
{
const maxon::Error error = res.GetError();
if (error.IsInstanceOf<maxon::ErrnoError>())
{
// cast into ErrnoError and access error code
const maxon::ErrnoError errnoError = maxon::Cast<maxon::ErrnoError>(error);
const maxon::Int errorCode = errnoError.GetErrorCode();
DiagnosticOutput("Error Code: @", errorCode);
}
}

Further Reading

Int
maxon::Int Int
Definition: ge_sys_math.h:49
maxon::end
MAXON_ATTRIBUTE_FORCE_INLINE auto end(COLLECTION &&c) -> decltype(c.End())
Definition: foreach.h:360
maxon::Class
Definition: objectbase.h:671
maxon
The maxon namespace contains all declarations of the MAXON API.
Definition: c4d_basedocument.h:27
MAXON_IMPLICIT
#define MAXON_IMPLICIT
Definition: apibase.h:168
maxon::String
Definition: string.h:1199
maxon::OK
return OK
Definition: apibase.h:2462
maxon::Bool
bool Bool
boolean type, possible values are only false/true, 8 bit
Definition: apibase.h:177
maxon::Id
Definition: apibaseid.h:273
iferr_return
#define iferr_return
Definition: resultbase.h:1419
MAXON_SOURCE_LOCATION
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:66
maxon::BaseArray
Definition: basearray.h:366
DiagnosticOutput
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:168
maxon::GetCount
Int GetCount(const ITERABLE &iterable)
Definition: collection.h:37
maxon::src
const T & src
Definition: apibase.h:2455
maxon::Result< void >
maxon::BaseArray::GetCount
MAXON_ATTRIBUTE_FORCE_INLINE Int GetCount() const
Definition: basearray.h:527
maxon::Int
Int64 Int
signed 32/64 bit int, size depends on the platform
Definition: apibase.h:184
iferr_scope
#define iferr_scope
Definition: resultbase.h:1328
maxon::FAILED
static const ERROR_FAILED FAILED
Definition: resultbase.h:68
maxon::Col3
A color consisting of three components R, G and B.
Definition: col.h:14
maxon::Result::GetError
const Error & GetError() const
Definition: resultbase.h:1026
NewObj
#define NewObj(T,...)
Definition: newobj.h:108
maxon::BaseRef
Definition: apibase.h:1500
maxon::BaseCollection< BaseArray< T, BASEARRAY_DEFAULT_CHUNK_SIZE, BASEARRAYFLAGS::NONE, DefaultAllocator >, BaseArrayData< T, DefaultAllocator, std::is_empty< DefaultAllocator >::value > >::CopyFrom
MAXON_ATTRIBUTE_FORCE_INLINE Result< void > CopyFrom(COLLECTION2 &&other, COLLECTION_RESIZE_FLAGS resizeFlags=COLLECTION_RESIZE_FLAGS::FIT_TO_SIZE)
Definition: collection.h:248
maxon::StrongRef
BaseRef< T, StrongRefHandler > StrongRef
Definition: baseref.h:884