Global static classes?
-
In the documentation i read the following:
Do not use global static classes of complex types. Elementary data types (Int32, Float, Char etc.) are allowed, see Primitive Data Types Manual (Cinema API).
Im not sure what this exactly means. But im trying to create a settings class as a static member to ShaderData nodes that contains information about the derived class that the base class needs to know.
struct InfoStruct { public: UInt32 SomeID; Int32 SomeUI; }; PluginNodeBase : public ShaderData { INSTANCEOF(PluginNodeBase, ShaderData) public: virtual PluginNodeInfoStruct& PluginNodeInfo() const = 0; } class SomeClass: public PluginNodeBase { INSTANCEOF(VolumeMedium, PluginNodeBase) public: // Set plugin node info inline static PluginNodeInfoStruct sPluginNodeInfo { SOME_ID, SOME_UI_ID, }; virtual PluginNodeInfoStruct& PluginNodeInfo() const override { return sPluginNodeInfo; }; }
Would this be fine? or is there a reason Icould not use static in this way?
-
Hey @ECHekman,
Thank you for reaching out to us. You should avoid such things as
sPluginNodeInfo
(which I assume is meant to return anInfoStruct
and not aPluginNodeInfoStruct
and to be the focal point of your question). The correct way to do this in the context ofNodeData
plugin hooks, would be to place an uninitialized field on your node and then initialize it inNodeData::Init
(and possibly implementNodeData::CopyTo
,::Read
, and::Write
to also support copy and IO events). When you want a const value, implement a function which returns a const value each time when called, possibly pulling up an internal value (a 'getter' property) or simply returning a new value each time.You will land in a world of hurt sooner or later when you ignore this in our API (as in access violations, I just had a dev internally who tried to pull up point data in this manner and then ran into said access violations). Your case is probably fine, but you should not do this. I personally would also avoid marking functions as virtual which are not.
SomeClass::PluginNodeInfo
is likely meant to be a concrete implementation and therefore should not be virtual.The same thing applies to global instances (which is probably what was meant in docs primarily).
// Not a good idea ... static InfoStruct g_info; int main() { g_info.Foo(); return 0; }
Cheers,
Ferdinand -
Could you explain the issue with this though? Is C4D doing strange stuff with c++ classes derived from ShaderData?
I wanted to avoid having to recreate the PluginNodeInfoStruct every time an instance is created by placing it in ::Init. Would the following be fine?
virtual PluginNodeInfoStruct& PluginNodeInfo() const override { static PluginNodeInfoStruct sPluginNodeInfo { SOME_ID, SOME_UI_ID, }; return sPluginNodeInfo; };
-
As I said, you will run into access violations when you instantiate your fields on the class instead of the
Init
function. And as I also said, in your concrete case it would probably even be fine if you would directly do it in the class scope. But I would advise against breaking this rule. There is nothing to optimize here, either return a new instance when this is only called once in a blue moon and you do not want to bother with initializing a field. Or define a field and initialize it up inNodeData::Init
. And no, scene elements (NodeData
) should not share data on their class. We have types in the Maxon API to deal with this when you really want some heavy data structure which shall be initialized exactly once, but that is total overkill in this case.Cheers,
Ferdinand