Some questions regarding c++ class



  • On 15/03/2017 at 02:46, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:    
    Platform:      
    Language(s) :     C++  ;

    ---------
    Hi I'm currently moving slowly from python to C++ :D (Then be prepared to have a lot of questions in a couple of week :p)

    I never coded before in C++ so I might miss some C++ functionality.

    My first question is about GeData. What the benefice of them instead of using template?
    When should I use GeData?

    My second one is what the difference beetween a BaseArray, AtomArray(child of BaseArray?), BaseLinkArray
    Since I can put every data type in my BaseArray and this will work. So why other class exist ^^.
    And what the goal of a BlockArray? I don't really understand what is a block.
    What the difference beetwen thoses and a BaseListHead since BaseListNode can store any type if I'm right.

    Anyway thanks in advance ! :)



  • On 16/03/2017 at 10:29, xxxxxxxx wrote:

    Hi,

    the answer to many of your questions is "for historic reasons".

    Not sure, you have already seen the GeData manual. Personally I never had a reason to make use of GeData directly, except in cases it needs to be passed to or is returned by one of our API functions.
    For example we recommend to rather use Get-/SetParameter() (which both involve use of GeData) instead of accessing the BaseContainer of a node directly (as this enables the node's implementation to take part in the getting and setting of parameters and for example, update member variables in the process or even decide to not store data in the BaseContainer at all).
    In general you are right, something similar could also have been achieved with C++ templates, but for reasons beyond my knowledge, the developers decided to go the GeData route. And I'm pretty sure, they had good reasons to do so. One advantage of the GeData approach is of course, that you can work with GeData without knowing anything about the contained data type. For example you can read a parameter and pass it on to another place (e.g. write it into a BaseContainer) without a single line of code caring for the contained data type.

    For the arrays, this really is a grown topic and for the most part BaseArray is your best choice. It's more versatile and supports more modern C++ features than, lets say, AtomArray. And the best part, BaseArray is highly optimized. But again, the API is grown in many, many years and we can't change it easily without breaking existing plugins, so there will certainly be functions where you need either type of array.

    For the AtomArray there's also a manual as it is still one of the more commonly used array types. But I'm pretty sure, we'll deliver one for BaseArray as well.

    The BaseLinkArray is more or less a convenience version of BaseArray to store BaseLinks.

    BlockArray is a "memory optimized" array. As the API docs state, it provides you with means to preallocate blocks (hence the name, from memory block) of certain size, thus reducing the need for new allocations, when inserting elements. The need for this highly depends on your algorithm. Usually if not sure about the needs, you'll use a BaseArray first and in a later optimization process you might switch to a BlockArray.

    BaseListHead and BaseListNode are in a way the "successors" of GeListHead and GeListNode. But while with the "Ge" versions, the list node was part of the inheritance chain of a C4DAtom and thus these worked only with C4DAtom derived entities, the "Base" variants can now, as you correctly stated, build lists with arbitrary data types. With BaseListHead being somewhat the anchor of the list and BaseListNodes being, well, the nodes or elements in the list.

    Cheers,
    Andreas



  • On 17/03/2017 at 01:46, xxxxxxxx wrote:

    Thanks you a lot Andreas it really make way more sense for me !
    For resuming if I just have to store obj. BaseArray will be the best choice but if I want to interact with the scene it will be more userfriendly to simply have to manage an AtomArray.
    For exemple let's assume I want to get all obj selected and then do multiple check / iteration into those obj. Is it more efficency to assign a BaseArray with the AtomArray build from the doc->GetSelection ?

    Last question, what the difference beetween BlockArray and ArrayOfBlocks ?

    A litlle suggestion because I think there is few another deprecated/updated class by other one.

    Then I guess you should have a space in the SDK who telling us what class are updated and by which one. Or at least in each class which are deprecated a link with the one is preffered to use.
    I understand you want too keep old class for compatibility and it's very nice many other SDK just don't give a sh*t about that.

    Anyway thanks for everything you guys rocks at support ! :)

    EDIT: I got another stupid question but I don't really know if I should open a new thread or not for this...
    In this exemple :
    https://github.com/PluginCafe/cinema4d_cpp_sdk/blob/master/source/tool/snaptool.cpp

    At line 142 you have

    		doc->AddUndo(UNDOTYPE_CHANGE, op);
    

    But StartUndo and EndUndo is never called. Does undo are managed differently than in python?
    By reading the SDK is look like no. But I prefer ask ! :)



  • On 17/03/2017 at 09:24, xxxxxxxx wrote:

    ArrayOfBlocks is a convenience class to work with BlockArray. No need to mention, docs are weak here...

    Regarding your suggestion, I'm not quite sure. While I admit, we can certainly improve here, we do have at least the API Changes. Unfortunately only back to R15. We also can't deprecate classes/types, which are still widely used by our API. So long these have to coexist.

    Undo: No, undo in Python and C++ work the same. Just ToolData plugins (and types derived thereof) are a bit different in this regard. Unfortunately we have no docs on this topic, yet. Sorry. But at least there's a bunch of ToolData examples, which demonstrate it.

    Finally as a rule of thumb, if you are thinking about opening a new thread, please feel free... 😉



  • On 23/03/2017 at 03:21, xxxxxxxx wrote:

    Thanks you Andreas !

    Another suggestion but again it's just a suggestion. And you won't believe me but I actually find an advantage from python sdk to the c++ one. :p
    It would be really nice like in the python sdk to have a state or when those functions where implemented.
    But it's a huge work for something we can directly check in API changes. But when you work is always good to have the informations directly and not to check another page.

    In the c++ sdk what does exactly mean "the owner own the pointer".
    Does it mean if I free the ressource linked to his it will also be delete for other?
    Or does I just own the pointer, so I can't set/delete the data but I can create a new one and replace the pointed data?



  • On 23/03/2017 at 10:57, xxxxxxxx wrote:

    Hi,

    actually we do mark updated functions in the C++ SDK as well. Unfortunately this wasn't done all times, so there are many without such marks. But a tleast for R17 or R18 you should see these. For example on VoronoiFracture class or BaseObject::FindBestEulerAngle() function it says "Since R18". And we'll of course continue with this in the future.

    Regarding ownership of objects, we had quite an extensive discussion (in a thread which "fortunately" was about a completely different topic...) : Create and insert material
    I recommend you check this thread and afterwards, if there are still open questions, then please open a new thread and we'll continue the discussion in there.



  • On 23/03/2017 at 14:06, xxxxxxxx wrote:

    Hoo yeah I didn't see thoses. You really make fantasric stuff at maxon and specialy you support guys ! :)

    Thanks for the topic it's very interesting and he probably should be stiky or at least be added to the Code style guide :)
    I guess I have to re-read it 2/3 time in a couple of week just to be sure to have fully understand it but it's nice. And moreover the difference beetwen AutoAlloc and Alloc shoud be more exposed (But Maybe it is like all my other questions in this thread :p).

    I just got a litlle question about this code

        
        
            //Create the empty material pointer
        
            BaseMaterial* mymat = nullptr;
        
          
        
        
            //Check if the material already exists
        
            mymat = doc->SearchMaterial("my mat");
        
            if (!mymat)
        
            {
        
                myMat = BaseMaterial::Alloc(Mmaterial);
        
                if (!myMat)
        
                    return;
        
          
        
        
                myMat->SetName("my mat");
        
                myMat->SetParameter(MATERIAL_COLOR_COLOR, Vector(1, 1, 0), DESCFLAGS_SET_0);
        
                doc->InsertMaterial(myMat);
        
            }
        
            // Here myMat is a valid pointer to your material
        
            // But remember, the owner of the material pointed to by myMat is C4D at this point
        
            // ...
    

    Then after passing the lead to c4d each time I will use my myMat pointer I have to check if it's not a nullptr? If yes that mean each time we saw c4d own the pointer we have to check if it's not a nullptr.

    Since the topic cover error checking and so on.
    What's the best way for cehcking if a function who must return a Vector (or Matrice or anything like that which is not a bool or pointer) fails.
    1 - Never do this but make them returning a pointer to this datatype. Like that I can return a nullptr in case of fail. (I guess it's this one ^^)
    2 - Add a bool / int pointer varible to my paramater. And in case of fail write some value to them. And after checking the value.
    3 - Maybe there is a better way? Is it possible to detect if variable is just initialized but not assigned?

    Anyway thanks you for everything it's a gold mine of informations !



  • On 24/03/2017 at 06:43, xxxxxxxx wrote:

    Hi,

    you check the pointer once, regardless, if you allocated the object yourself or received it from C4D (except cases where it is explicitly mentioned that the pointer can not be nullptr). This has nothing to do with ownership, but with memory allocations and chances of these failing.
    Then for example at the "// ..." point of your code you can rely on the object existing. But lets assume, Cinema 4D is the owner, as in your code example. Either you are running in main thread or you are running in threaded context. In first case there's no one, who could delete the object (remember scene changes only from main thread, as stated everywhere). And in the later case, somebody wanting to delete the object would need to call stop all threads before modifying the scene.
    So there's nothing to be afraid of, if Cinema own a certain object.

    Regarding your last compound of questions, I'm not sure I understand and furthermore I'm not sure we are not leaving the area of C4D SDK related questions. In general there are many ways to achieve things in C++. And maybe references should also be considered in this group of questions.



  • On 24/03/2017 at 08:33, xxxxxxxx wrote:

    @gr4ph0s.
    The material creation code you posted is basically the smallest amount of code you can use to create a material. It will work in most typical use cases. But it's really just the base starting point.
    If you do anything more complex than creating a material(it's hard to give you an example).  Then using smart pointers like AutoAlloc can be very helpful in keeping your code safe from accidental memory leaks.
    This will very often not be needed if you do simple common tasks that the SDK was designed for.
    But if you start doing complex things that the are not the norm. Then smart pointers become much more important to use. Since you can't always think of every single way the code can fail while it's still holding onto some memory.
    That's really what the overall message of that thread is.

    IMO. The most important tool the C4D SDK has for new C++ users is the Debug tool (not the one inside of VS).
    It makes a command window open when running C4D from VS. And when you close C4D. It will list out any memory leaks you have created in your code.
    When I started out, I was new to C++ and writing lots of BaseBitmap code. Which often does not get owned by C4D. And I was not using the debug tool.
    When I finally used it. I discovered that I had lots of memory leaks in my code that I didn't know about.
    So my advice is to use that tool every time you write a C++ plugin. If nothing else. Just for peace of mind that you didn't accidentally miss something.

    -ScottA



  • On 24/03/2017 at 08:45, xxxxxxxx wrote:

    Good point, Scott. We actually call it the debug mode.
    And we have an article on debugging also showing how to activate this debug mode.



  • On 27/03/2017 at 01:59, xxxxxxxx wrote:

    Thanks you both it's very helpfull.
    Sadly I didn't succely lunch C4D with his white console in debug mode, while I succefully get it lunched via cmd.
    I currently use R17 and this is my configuration for arguments.

    -debug g_console=true
    

    Btw I don't really understand what the difference beetween g_alloc=debug and -debug. Using the cmd for lunching the litlle debug console. That said me Release or Debug.
    What the prefered one? Or should I choose one and don't care? :)

    Another question but I guess it's related to how tool behave with toolData plugin.
    But why this function is overloaded in the header of exemple project? Should I let it or not?

    Bool AddUndo(BaseDocument* doc, AtomArray* arr, UNDOTYPE type);
    


  • On 27/03/2017 at 08:41, xxxxxxxx wrote:

    I personally find the documentation for setting up the debugging a bit hard to understand. Because the command line setup is sandwiched in the middle of setting up the VS debugger.
    I find this to be confusing. Especially for people new to C++ and VS.

    In R13. There are two ways I can set up the VS debugger with the pop up command window:
    #1
    In configuration properties Debugging
      -Set Command to:            C:\Program Files\MAXON\CINEMA 4D R13\CINEMA 4D.exe
      -Set Working Directory to: C:\Program Files\MAXON\CINEMA 4D R13\
    Put an empty c4d_debug.txt file in the MAXON\R13 folder where the .exe files are

    #2
    In configuration properties Debugging
      -Set Command to:             C:\Program Files\MAXON\CINEMA 4D R13\CINEMA 4D.exe
      -Set Working Directory to:  Leave this empty
    Put your empty c4d_debug.txt file in the plugin's folder

    I could be wrong about this.
    But AFAIK. The -debug g_console=true thing a separate subject.
    It's a different way to debug using the command line. And should not be mixed into the VS instructions. And should be done after you have the VS debugger figured out and working.

    -ScottA



  • On 27/03/2017 at 09:35, xxxxxxxx wrote:

    Hi

    @gr4ph0s: I really think for the ToolData question you should open a separate thread, otherwise this thread will derail completely.

    -debug in general enables the debug mode, providing for example certain warnings.
    g_alloc=debug on the other hand sets the C4D's memory allocator into debug mode, providing you with nice features like a leak report, when quitting C4D.

    @gr4ph0s: I'm not sure I understand the questions after "Using the cmd for launching...". Who's saying what? And prefers whom? Probably you will need to care, but please try to explain the questions to me once more.

    @Scott: Nope, I wouldn't regard this different topics. You can set the command line options in VS (Project Properties->Debugging). And you'll get the output in VS's Output window, no need for a dedicated command line window.

    And for future readers, since R15 there's no need anymore for the c4d_debug.txt file, Scott is talking about.



  • On 27/03/2017 at 09:58, xxxxxxxx wrote:

    LOL. I'm falling so far behind with the changes that I'm starting to feel out dated.
    Grampa Scott says: "Back in my day. We used an empty .txt file to debug. And we walked to school barefoot...uphill....both ways. And we liked it that way." 😂

    -ScottA



  • On 27/03/2017 at 12:10, xxxxxxxx wrote:

    @Andreas
    Ok I will open new thread after some time cause I'm sure it's something I miss in the sdk, and I don't really dive into it for the moment.

    Here is my project setting for debugging. I can succefully lunch it in debug mode, but I don't get the console.
    http://img4.hostingpics.net/pics/512147debug.jpg

    By lunching it via cmd I succefully get the maxon console.
    "C:\Program Files\MAXON\CINEMA 4D R17_dev\CINEMA 4D.exe" g_alloc=debug g_console=true

    @Scotta
    Haha maybe you are old but you got the knowledge then who care?
    The .txt method worked but I really prefer to use the maxon's console  :p



  • On 27/03/2017 at 23:42, xxxxxxxx wrote:

    Hi,

    Scott, you made my day (and it's just 8:37 around here) 🙂
    Maybe we should compare our mileage one day (of course in secrecy, otherwise the rest of the community probably starts making fun of the elder)? Or we could have an old people's home sub-forum, where we discuss the APIs of early releases?

    @gr4ph0s: When running in debugger, the VS output window takes over the role of the command line window.


Log in to reply