BaseArray in Struct, how to manage [SOLVED]



  • On 29/04/2017 at 10:42, xxxxxxxx wrote:

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

    ---------
    Hi I would like to have an BaseArray into a struct. But I didn't succes to fill it after.
    Here is a sample code without error checking.

    typedef struct iobject{
        String name;
        maxon::BaseArray<Int32> uvCount;
    };
      
    iobject* objectData = new iobject();
      
    //don't work
    objectData->uvCount.Append(42);
      
      
    //don't work either
    maxon::BaseArray<String> buffer = objectData->uvCount;
    buffer.Append(42)
    objectData->uvCount = buffer;
      
    //seem to work but why other doesn't?
    objectData->uvCount.Insert(objectData->uvCount.End, 42);
    

    Thanks in advance



  • On 02/05/2017 at 13:21, xxxxxxxx wrote:

    Hi gr4ph0s, thanks for writing us.

    Unfortunately, as far as I tried to, I'm unable to replicate your issue under Mac or under Window.
    Although my tests have been successful either using new or NewObj() I warmly suggest to use the last one in order to optimise memory allocation and memory management under Cinema 4D. In order to get an overall overview on the topic have a look at the Entity Creation and Destruction Manual in Cinema API documentation

    Additionally I don't get what's the real intent of the code following the comment "//don't work either" which to me looks pretty odd.

    Last but not least beware of deallocating the newly created object to avoid memory leaks: depending on the fact that you decided to use "new" or "NewObj()" use respectively "delete" or "DeleteObj()" to free the allocated resources.

        typedef struct iobject
        {
            String mystring;
            maxon::BaseArray<Int32> mybasearray;
        } DUMMYTYPE;
        
        // instantiate a new object
        DUMMYTYPE* objDummyType = new DUMMYTYPE();
        
        // check the existence of new object
        if (!objDummyType)
            return false;
        
        // append some values
        objDummyType->mybasearray.Append(-1);
        objDummyType->mybasearray.Append(-10);
        objDummyType->mybasearray.Append(-100);
        
        // check the stored values
        for (Int32 i = 0; i < objDummyType->mybasearray.GetCount(); ++i)
        {
            GePrint("objDummyType->mybasearray[" + String::IntToString(i) + "]: " + String::IntToString(objDummyType->mybasearray[i]));
        }
        
        // deallocate the instance
        delete (objTypeA);
    

    Best, Riccardo



  • On 02/05/2017 at 15:00, xxxxxxxx wrote:

    Thanks for taking time to answerd me.

    Yeah about the string was just a bad copy/cat from myself.

    I guess my error is how I handled struct. But anyway I figured out and with your example I understand why !



  • On 04/05/2017 at 04:54, xxxxxxxx wrote:

    Sorry for the double post but I guess it's the only way for bumping it.
    In this case how to handle thing properly?

    struct MyStructB{
        maxon::BaseArray<Int32> ArrayOfInt;
        };
      
    struct MyStructA{
        maxon::BaseArray<MyStructB> ArrayOfIntArray;
        };
      
    AutoNew<MyStructA> myVar;
    

    What must be my constructor for MyStructB?
    Coz I always got error C2248 while nothing is declarated as private.
    So I guess it's the BaseArray who got some parameters marked as private.
    Error 10 error C2248: 'maxon::BaseArray<Bool,0x010,BASEARRAYFLAGS_0,maxon::DefaultAllocator>::BaseArray' : cannot access private member declared in class 'maxon::BaseArray<Bool,0x010,BASEARRAYFLAGS_0,maxon::DefaultAllocator>'

    So far the only solution I found was to convert ArrayOfInt into vector instead of BaseArray. But I would like to use maxon api since STL is not recommended.



  • On 04/05/2017 at 08:42, xxxxxxxx wrote:

    Hi gr4ph0s, first thanks for keeping asking.

    With reference to your question, I suggest you to have a look inside the basearray.h at the BaseArray template definition. There you'll find a MAXON_DISALLOW_COPY_AND_ASSIGN preprocessor directive which basically prevents copying the class specified (in our case the BaseArray itself).

    Because of this directive you're provided by the compiler with the C2248 error you've reported. Basically when you try to store a new instance of MyStructB into the ArrayOfIntArray pointed by myVar the directive prevents your instance to get copied and assigned to the appended entry of the ArrayOfIntArray.

    In order to make everything working smoothly, you have to store pointers to MyStructB in the BaseArray in MyStructA and operate accordingly

            struct MyStructB{  
              maxon::BaseArray<Int32> ArrayOfInt;  
          };
      
            struct MyStructA{  
              maxon::BaseArray<MyStructB*> ArrayOfIntArray;  
          };
      
            // auto-allocate an instance of MyStructA  
          AutoNew<MyStructA> arrStructB;
      
            // check the pointer of the allocated instance  
          if (!arrStructB)  
              return;
      
            // append an pointer going to point to a 'soon-to-be-allocated' MyStructB  
          arrStructB->ArrayOfIntArray.Append();
      
          // allocate the MyStructB instance and save the memory location in the pointer  
          arrStructB->ArrayOfIntArray[0] = NewObjClear(MyStructB);
      
          if (arrStructB->ArrayOfIntArray[0])  
          {  
              // fill the newly created instance of MyStructB  
              arrStructB->ArrayOfIntArray[0]->ArrayOfInt.Append(1);  
              arrStructB->ArrayOfIntArray[0]->ArrayOfInt.Append(10);  
              arrStructB->ArrayOfIntArray[0]->ArrayOfInt.Append(100);  
          }
      
            // append another pointer going to be point to another MyStructB  
          arrStructB->ArrayOfIntArray.Append();
      
          // allocate the MyStructB instance and save the memory location in the pointer  
          arrStructB->ArrayOfIntArray[1] = NewObjClear(MyStructB);
      
          if (arrStructB->ArrayOfIntArray[1])  
          {  
              // fill the newly created instance of MyStructB  
              arrStructB->ArrayOfIntArray[1]->ArrayOfInt.Append(2);  
              arrStructB->ArrayOfIntArray[1]->ArrayOfInt.Append(20);  
              arrStructB->ArrayOfIntArray[1]->ArrayOfInt.Append(200);  
          }
      
            // check that everything is properly stored  
          for (int i = 0; i < arrStructB->ArrayOfIntArray.GetCount(); ++i)  
          {  
              MyStructB* pMyStructB = arrStructB->ArrayOfIntArray[i];  
              for (int j = 0; j < pMyStructB->ArrayOfInt.GetCount(); ++j)  
              {  
                  Int32 value = pMyStructB->ArrayOfInt[j];  
                  GePrint("[" + String::IntToString(i) + "," + String::IntToString(j) + "]: " + String::IntToString(value));  
              }  
          }
      
            // deallocate each instance pointed by the pointers stored in the MyStructA instance  
          for (int i = 0; i < arrStructB->ArrayOfIntArray.GetCount(); ++i)  
          {  
              DeleteObj(arrStructB->ArrayOfIntArray[i]);  
          }
    

    Best, Riccardo



  • On 04/05/2017 at 10:09, xxxxxxxx wrote:

    Thanks you a lot riccardo for taking time to answerd me.

    Btw NewObjClear is just for allocating memory while NewObj allocate the objet. Isn't it?



  • On 16/05/2017 at 06:50, xxxxxxxx wrote:

    Hi gr4ph0s,

    the former allocates the memory block hosting the object instance and clear it while  the second just allocates the memory block.

    Best, Riccardo


Log in to reply