passing arrays as parameters
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 31/03/2012 at 04:34, xxxxxxxx wrote:
Originally posted by xxxxxxxx
- this pointer thing samir suggested ( i still don't fully understand althought i am aware of the pointer nature of arrays).
2. using c++ 11
3. external libs
1. This is the clean way to do it And it's also super simple. Declare the array in your code before using the function, allocate it and call your function later and after you're done with the array, don't forget to free it.
Bool foo (LONG *myarray, LONG count) { if (!myarray || count == 0) return FALSE; // As an example: Fill the array with numbers LONG i; for (i = 0; i < count; i++) { myarray[i] = i*i; } return TRUE; } Bool PrintArray(LONG *myarray, LONG count) { if (!myarray || count == 0) return FALSE; LONG i; for (i = 0; i < count; i++) { GePrint("Array[" + LongToString(i) + "] = " + LongToString(myarray[i])); } return TRUE; } ... ... void main() { const LONG count = 100; // Allocate array LONG *arr = GeAllocType(LONG, count); if (!arr) { GePrint("Error allocating the array"); return; } // Fill the array if (!foo(arr, count)) GePrint("Filing the array didn't work out."); else GePrint("Array filled succesfully"); // Do something with the filled array if (!PrintArray(arr, count)) GePrint("Could not print out array."); // Free memory if (arr) GeFree(arr); }
You could also allocate the array in the same function where it's being filled with values and then return the new array:
LONG* foo (LONG count) { if (count == 0) return NULL; LONG* myarray = GeAllocType(LONG, count); if (!myarray) return NULL; // As an example: Fill the array with numbers LONG i; for (i = 0; i < count; i++) { myarray[i] = i*i; } return myarray; } ... ... void main() { const LONG count = 100; // Allocate array LONG *arr = foo(count); if (!arr) { GePrint("Error allocating and filling the array"); return; } // Do something with the filled array if (!PrintArray(arr, count)) GePrint("Could not print out array."); // Free memory if (arr) GeFree(arr); }
2. The C4D API is currently not compatible with C++ 11 standard. Enabling C++ 11 in your compiler might lead to problems with the API code.
3. External libs might create extra hassle for you when compiling them for different platforms. As - quite frankly - you seem to be a beginner with C++, I would not recommend to use them.
Also, try to use the types defined in the C4D API (e.g. LONG instead of int), that will keep you from running into problems with 32 bit vs. 64 bit, different platforms and single precision vs. double precision.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 31/03/2012 at 05:58, xxxxxxxx wrote:
hi,
thank you for your extensive code example, it is very much appreciated. just as a sidenote, i am
aware of point 2-3 and yes i am a beginner :). -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 31/03/2012 at 08:38, xxxxxxxx wrote:
@jack: Just a note, returning allocated memory from a function is considered bad. It's also some kind of confusing (imho).
-Niklas
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 31/03/2012 at 08:42, xxxxxxxx wrote:
Returning memory from a method is okay as long as you are cognizant that your are 'passing' ownership from the method to somewhere else so that it can be freed properly by the new owner. The scope may be lost when returning from the method but as long as you have assigned a pointer to the new allocation that has more lasting scope, you should be okay.
Edit to add:
if (arr) GeFree(arr);
The conditional is not necessary. If 'arr' is NULL then GeFree doesn't do anything (and it won't crash). You've already checked that arr isn't NULL so it should be doubly okay. One case to remember is that if you free memory and the execution continues you should set the pointer to it equal to NULL. So, this is better:
GeFree(arr);
arr = NULL; // Make sure that it doesn't point to memory that it no longer owns!Any subsequent GeFree() calls (such as in a destructor) will do the appropriate thing. Otherwise, you risk trying to free the same memory twice - and crash.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 01/04/2012 at 03:00, xxxxxxxx wrote:
Originally posted by xxxxxxxx
@jack: Just a note, returning allocated memory from a function is considered bad. It's also some kind of confusing (imho).
If it was considered bad, I don't think we would have any Alloc() functions in the API...
BaseObject *op = BaseObject::Alloc(Onull);
In fact, even the memory allocation is done by a function:
LONG* myarray = GeAllocType(LONG, count);
And yes, it might be confusing. But programming is a confusing thing if one does not take care Therefore, we wouldn't call this function "foo" but rather something with "Alloc".
Originally posted by xxxxxxxx
if (arr) GeFree(arr);The conditional is not necessary. If 'arr' is NULL then GeFree doesn't do anything (and it won't crash). You've already checked that arr isn't NULL so it should be doubly okay.
Right, in this example it was obvious. But it'S better to have double and triple checks than to run into some surprising case (in more complex code) and have it crash on the user's machine.
Originally posted by xxxxxxxx
One case to remember is that if you free memory and the execution continues you should set the pointer to it equal to NULL.
With GeFree and also with the static Free methods of the C4D API classes, that is not necessary. They set your pointer to NULL automatically (pointer reference (void*& p)). Same with the gDelete and bDelete macros.
But generally, of course, one should take care to set the pointer to NULL when any other method of memory freeing is used.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 01/04/2012 at 04:45, xxxxxxxx wrote:
Originally posted by xxxxxxxx
Originally posted by xxxxxxxx
@jack: Just a note, returning allocated memory from a function is considered bad. It's also some kind of confusing (imho).
If it was considered bad, I don't think we would have any Alloc() functions in the API...
BaseObject *op = BaseObject::Alloc(Onull);
Sorry didn't add that. We have Free() functions according to them, which is not considered bad.
-Niklas -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/04/2012 at 00:43, xxxxxxxx wrote:
hi,
i have got another question. i am still messing with my objectdata plugin. it basicly returns
different geometry types based on data entered by the user (disc,plane,sphere...). as they
extend some of basic capeabilities of c4ds baseobjects i thought it would be smart to
outsource their allocation.currently it is something like this :
BaseObject *Opolylight::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh) { ... return GetPlane(op); } static BaseObject *Opolylight::GetPlane(BaseObject *op) { BaseObject *result = NULL; result = BaseObject::Alloc(Oplane); BaseContainer *outbc = result->GetDataInstance(); BaseContainer *inbc = op->GetDataInstance(); ... return result; }
i am roughly following the SDK ATOM sample. but while the atom sample is just outsourcing into
one other method form GetVirtualObjects, in my case it would make sense to have one method
for each objecttype (GetPlane, GetDisc ...).my question is now : when the user changes the ouput from plane to disc the allocated mem from
GetPlane still remains alltough it isn't used anymore. by defining the method as static i prevent
the code from creating multiple instances, but my addon will still carry a bunch of data for each
shape the user has choosen once.is this considered as a memory leak / bad ?
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/04/2012 at 01:48, xxxxxxxx wrote:
Do you mean, the function itself still exists and redundant when not used anymore?
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/04/2012 at 01:56, xxxxxxxx wrote:
the function is a pointer pointing on a baseobject, but somewhere this chain of pointer madness
has to end, in my example it ends at result = BaseObject::Alloc(Oplane);. i thought it works this
way :1. GetVirtualObjects is called
2. GetVirtualObjects calls GetPlane
3. GetPlane allocates some memory at adress xyz and creates a BaseObject there
4. GetPlane returns xyz
5. GetVirtualObjects is called again
6. GetVirtualObjects calls GetSpherewhat happens with the BaseObject @ memory adress xyz ?
i guess i am geting something wrong again
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/04/2012 at 02:21, xxxxxxxx wrote:
In the SDK are often notes that say "Cinema 4D owns the pointed/returned object." which means Cinema will manage the memory of the object. I can't find such a note in the ObjectData::GetVirtualObjects() documentation. They either forgot to add it or you have to manage that on your own, i.e. cache the object and free it on the next call to GetVirtualObjects(). I haven't written a C++ plugin yet, (as I said, I refuse to use VC. ).
Cheers,
-Niklas -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/04/2012 at 02:37, xxxxxxxx wrote:
uh i made a mis take in my example, when i shortend the code, it has to be
static BaseObject * ~~Opolylight::~~ GetPlane(BaseObject *op) { BaseObject *result = NULL; result = BaseObject::Alloc(Oplane); BaseContainer *outbc = result->GetDataInstance(); BaseContainer *inbc = op->GetDataInstance(); ... return result; }
of course. @ nikklas i am not talking about GetVirtualObjects, it is called on each update and there are examples in the sdk how to treat cases in which GetVirtualObject fails to produce a propper output (free the memory). but i have firgured it out somehow i guess, i have just to create some kind of garbagecollector method which clears all the unused static pointer method adresses. i'll report back when i fail again :) ps : refusing to praise & and use microsoft products is considered to be a mortal sin by the spanish inquisition.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/04/2012 at 05:27, xxxxxxxx wrote:
Whatever object you return in GetVirtualObjects(), don't care about its memory anymore. Cinema takes over the ownership.
If you allocate an object but don't return it at the end of GetVirtualObjects(), you have to free it yourself of course.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/04/2012 at 08:44, xxxxxxxx wrote:
hi,
and here i am again, i tried to check my code so i placed a c4d_debug.txt in my c4d folder.
first i started c4d from the desktop and the console window said meh, debugger not present
so i started c4d from vs using my project (which compiles and runs fine atm), c4d crashes again
with the exception floating point division by zero. so i tried the sdk_examples with the 32 bit debug
platform. it starts without any errors, but the console doesn't show up, not while debugging, not after.i am on vista 64 bit, c4d demo 32 bit and VS 8.0.5
has someone experience with this odd behaviour ?
sorry, for throwing random questions at you
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 02/04/2012 at 22:05, xxxxxxxx wrote:
for the Console to show up you need to set the startup directory in VS to the c4d folder (project properties -> debugging). Else it won't find the c4d_debug.txt
or you put the c4d_debug.txt in the plugin's folder -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 03/04/2012 at 01:29, xxxxxxxx wrote:
Originally posted by xxxxxxxx
so i placed a c4d_debug.txt in my c4d folder.
Already said, that text file better goes into your plugin's folder. Otherwise, Cinema will do the memory trace everytime your start it, and that is usually not desired.
Originally posted by xxxxxxxx
i started c4d from vs using my project (which compiles and runs fine atm)
That's the right way to do. Create a Debug build in VS and use the "Play" button to start Cinema in the VS Debugger.
Originally posted by xxxxxxxx
c4d crashes again with the exception floating point division by zero.
so i tried the sdk_examples with the 32 bit debug
platform. it starts without any errorsThen the DivByZero is definitely a bug in your code ALWAYS check for zero before doing any division (or take care that zero will never occur).
Originally posted by xxxxxxxx
sorry, for throwing random questions at you
That's OK, but I really think you should open separate threads for separate questions. That way, it will be much easier for other people to find your questions and the answers.
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/04/2012 at 18:40, xxxxxxxx wrote:
Yes, I already said this. An argument will be put into a CPU register if available otherwise it goes onto the stack. This is why four or less arguments for a method are faster. As someone with nearly 30 years of programming and most of that using C/C++, I definitely know what the hell I'm talking about.
http://msdn.microsoft.com/en-us/library/zthk2dkh%28v=vs.80%29.aspx