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