Hi @tdapper thanks for reaching out us.
With regard to your comment, although I confirm that you don't have to put them in a separate framework but it's actually recommended to grant good design and straightforward reusability.
For the sake of clarity, find below the files used to create a project which includes both the declaration and the implementation of the custom error together with the code using it. The example is derived from the code presented on GitHub.
project/projectdefinition.txt
// Supported platforms - can be [Win64;OSX]
Platform=Win64;OSX
// Type of project - can be [Lib;DLL;App]
Type=DLL
// API dependencies
APIS=cinema.framework;mesh_misc.framework;math.framework;crypt.framework;python.framework;core.framework;
// C4D component
C4D=true
stylecheck.level=3 // must be set after c4d=true
stylecheck.enum-registration=false
stylecheck.enum-class=false
ModuleId=net.maxonexample.support.single_plugins.PC12316
source/PC12316_CustomErrorImpl.cpp
#include "PC12316_CustomErrorInterface.h"
// This example shows the implementation of a custom error type.
class PC12316_CustomErrorImpl : public maxon::Component<PC12316_CustomErrorImpl, PC12316_CustomErrorInterface>
{
// use ErrorObjectClass to implement basic error functionality
MAXON_COMPONENT(NORMAL, maxon::ErrorObjectClass);
public:
maxon::Result<void> CopyFrom(const PC12316_CustomErrorImpl& src)
{
_errorCode = src._errorCode;
return maxon::OK;
}
public:
MAXON_METHOD maxon::String GetMessage() const
{
return FormatString("Custom error code is @", _errorCode);
}
// custom methods
MAXON_METHOD void SetCustomErrorCode(maxon::Int errorCode)
{
_errorCode = errorCode;
}
MAXON_METHOD maxon::Int GetCustomErrorCode() const
{
return _errorCode;
}
private:
maxon::Int _errorCode; ///< error code value
};
// register all the non-static methods in the implementation
MAXON_COMPONENT_OBJECT_REGISTER(PC12316_CustomErrorImpl, PC12316_CustomErrorObject);
source/PC12316_CustomErrorInterface.h
#ifndef PC12316_CUSTOMERRORINTERFACE_H__
#define PC12316_CUSTOMERRORINTERFACE_H__
#include "maxon/object.h"
// This example shows the declaration of a custom error type.
// The custom error is able to store a custom error code.
// ---------------------------------------------------------------------
// Custom error class that stores an error code.
// ---------------------------------------------------------------------
class PC12316_CustomErrorInterface : MAXON_INTERFACE_BASES(maxon::ErrorInterface)
{
MAXON_INTERFACE(PC12316_CustomErrorInterface, MAXON_REFERENCE_COPY_ON_WRITE, "net.maxonexample.example.errors.PC12316_customerror");
public:
MAXON_ADD_TO_COPY_ON_WRITE_REFERENCE_CLASS(
void Create(MAXON_SOURCE_LOCATION_DECLARATION, maxon::Int errorCode)
{
#if API_VERSION >= 20000 && API_VERSION < 21000
* static_cast<typename S::DirectlyReferencedType::ReferenceClassHelper::type*>(this) = S::DirectlyReferencedType::ReferenceClassHelper::object::GetInstance() ();
#elif API_VERSION >= 21000
*static_cast<typename S::DirectlyReferencedType::Hxx1::ReferenceClass*>(this) = S::DirectlyReferencedType::Hxx1::ErrObj::GetInstance()();
#endif
typename S::DirectlyReferencedType::Ptr e = this->MakeWritable(false).GetPointer();
e.SetLocation(MAXON_SOURCE_LOCATION_FORWARD);
e.SetCustomErrorCode(errorCode);
}
);
// custom methods
// ---------------------------------------------------------------------
// Stores an custom error code.
// ---------------------------------------------------------------------
MAXON_METHOD void SetCustomErrorCode(maxon::Int errorCode);
// ---------------------------------------------------------------------
// Returns the stored custom error code.
// ---------------------------------------------------------------------
MAXON_METHOD maxon::Int GetCustomErrorCode() const;
};
#include "PC12316_CustomErrorInterface1.hxx"
#include "PC12316_CustomErrorInterface2.hxx"
#endif /* PC12316_CUSTOMERRORINTERFACE_H__ */
source/PC12316.cpp
#include "c4d.h"
static const Int32 PluginID = 99912316;
#include "PC12316_CustomErrorInterface.h"
// Dummy test function
maxon::Result<void> TestFunction(maxon::Int * val);
maxon::Result<void> TestFunction(maxon::Int * val)
{
iferr_scope;
if (!val)
return PC12316_CustomError(MAXON_SOURCE_LOCATION, 4242);
ApplicationOutput("Value is @", *val);
return maxon::OK;
}
// Command to test the custom error
class CustomErrorExample : public CommandData
{
public:
#if API_VERSION >= 20000 && API_VERSION < 21000
Bool Execute(BaseDocument* doc)
#elif API_VERSION >= 21000
Bool Execute(BaseDocument* doc, GeDialog* parentManager)
#endif
{
iferr_scope_handler
{
return false;
};
if (!doc)
return false;
iferr (TestFunction(nullptr))
ApplicationOutput("Error: @", err);
maxon::Int a = 100;
iferr (TestFunction(&a))
ApplicationOutput("Error: @", err);
return true;
}
static CommandData* Alloc() { return NewObj(CustomErrorExample) iferr_ignore("Unexpected failure on allocating CustomErrorExample plugin."_s); }
};
Bool RegisterCustomErrorExample();
Bool RegisterCustomErrorExample()
{
return RegisterCommandPlugin(PluginID, "PC12316_CustomErrorExample"_s, PLUGINFLAG_COMMAND_OPTION_DIALOG, nullptr, ""_s, CustomErrorExample::Alloc());
}
Bool PluginStart()
{
if (!RegisterCustomErrorExample())
return false;
return true;
}
void PluginEnd()
{
}
Bool PluginMessage(Int32 id, void* data)
{
return true;
}
A final minor note on register=true: since R21 it's not needed anymore because in former releases it was needed to specify when a module was supposed to run in pure legacy-mode but nowadays modules can be either hybrid (classic + maxon API) or maxon API-only.
Hoping this makes using our Error Handling system more clear and easy to integrate in your products, give best and don't hesitate to ask for more.
Best, R