Iterating through a pointer to a vector of pointers - iphone

I am trying to write an iPhone game using cocos2d and Box2D, which means I have to mix between Objective-C and C++. I have a question regarding using pointers to objects of gameLevels and levelObjects that I have created.
I have a class called GameLevel which contains a vector of levelObjects. I thought that using pointers was the way to do it, to make sure I use as little memory as possible. That means that my vector is
std::vector<LevelObject*>* levelObjects;
The LevelObject class contains the sprite, b2bodyDef and so on, all pointers as well.
The problems started when I wanted to iterate through this vector when I wanted to draw a level. The code I wrote was this:
-(void)startLevel:(b2World*) world withLevel:(GameLevel*) level{
std::vector<LevelObject*>::iterator it;
for (it = level->getLevelObjects()->begin() ; it != level->getLevelObjects()->end(); ++it) {
CCSprite* sprite = it->sprite; //Here XCode complaints about "Member reference base type 'LevelObject *' is not a structure or union" and "Use of undeclared identifier 'sprite'". I cannot seem to access any of the objects variables/methods from it->
So the question I ask is: Is this a good way to to this, with a pointer to vector of pointers? And why doesn't the iteration work?
Thanks :)
EDIT: getLevelObjects() are:
std::vector<LevelObject*>* getLevelObjects(){return levelObjects;}

Your iterators point to pointers, so you need two dereferences:
(*it)->sprite
the dereference of the iterator,
*it
gives you a LevelObject*.

You have two levels of indirection, the iterator and the pointer inside the vector.
You need (*it) to get to the pointer, and then use -> to dereference that:
CCSprite* sprite = (*it)->sprite;

Related

How can I assign a Swift struct by reference?

As we know, in Swift, classes are reference objects whereas structs other data-types are value types. I'm trying to get the reference of a CGRect into a variable so I can change its value with a shorter name. Is there a way to achieve this? Attempting with an Objective-C or C++ pointer syntax is of no use here :(
let reference = someView.frame
frame = ...
If I stay at the view level it's ok because it's a reference type, but I want to include the frame in the reference.
You probably don't really want to work with references... I could be wrong, and you might have a good reason for wanting a reference. But looking at what you are trying to do, this might be a better approach:
Assign the frame that you want to work with to a variable:
var workingFrame = someView.frame
Work with the copy, making any changes that you want to make:
workingFrame = someNewRect
Update someView.frame to the new value:
someView.frame = workingFrame
There is, technically, a way to deal directly with pointers to memory addresses, but unless you have an amazingly good reason for going there, I think that most people would recommend that you avoid it.
[Edit:]
If you really want to try to work with pointers to memory addresses, then you may want to look at UnsafePointer<T>, UnsafeMutablePointer<T>, unsafeBitCast: and unsafeAddressOf:. Those types and functions will give you pointers to a struct.
For example, you can get a mutable pointer to an Int value like this:
let x = 5
let ptr: UnsafeMutablePointer<Int> = UnsafeMutablePointer(unsafeAddressOf(x))
Working with values, pointers, and memory addresses this way is discouraged, but yes, it is possible.
However, using unsafeAddressOf converts the Int to a class, so even that isn't really a pointer to the original struct. You may end up needing to initialize an UnsafeMutablePointer, allocate memory for it, and then assign a value to that memory. Then you can perform operations on the data at that memory address. Check out the documentation for UnsafeMutablePointer here.
And if you can give any more detail as to what, precisely, you are trying to do, there may be a more elegant solution. Swift does not make it easy to work with pointers, but it often provides other tools that allow you to accomplish what you need in a different way.
Here's the solution:
func pointerTo<T>(inout object: T) -> UnsafeMutablePointer<T> {
return withUnsafeMutablePointer(&object) {UnsafeMutablePointer<T>($0)}
}

Malloc() creates space for single struct, not array of structs

I've been banging my head against this problem all day, I would be very grateful to anyone who could help out.
Here's the deal - I'm trying to create a dynamic C array using malloc(). This array will hold CGPoint structs, which I start building and assigning right after the array is built. Here's the code:
CGPoint* tempVertices = malloc(sizeof(CGPoint) * 4); //defining a collision frame
tempVertices[0] = CGPointMake(37, 46);
tempVertices[1] = CGPointMake(69, 40);
tempVertices[2] = CGPointMake(48, 6);
tempVertices[3] = CGPointMake(17, 10);
//Then I pass the pointer to my array off to a setter...
[self setVertices: tempVertices];
However, when tempVertices gets created, it seems that I'm only getting space for one CGPoint:
int test1 = sizeof(CGPoint); // 8
int test2 = sizeof(tempVertices); // 4
int test3 = sizeof(*tempVertices); // 8
When stepping through with the XCode debugger, it shows that tempVertices is a pointer to a CGPoint. When I set tempVertices[0], the CGPoint that tempVertices points to recieves that value, which is reflected in the debugger. Where did my other 3 slots go? tempVertices seems to be pointing to a singe CGPoint instead of an array. I want the array.
Any ideas on what I'm doing wrong? I know that there are other ways to fix this using C++ or other objects, but I want to stick to C if possible.
Thanks in advance!
Update :
To answer zpasternack, setVertices: is a custom written setter. And I don't know how / if it knows how big the incoming array is. I'm trying to understand straight C stuff better, so insights/explanations regarding the proper way of passing a dynamic C-array as an argument are highly appreciated. Here's what the setter looks like :
- (void) setVertices:(CGPoint*) val {
_vertices = val; //_vertices is a member variable of the type CGPoint*
//...calculate a centroid, other stuff...
}
If needed, I could wrap my CGPoints in NSValue objects and use an NSArray instead, but I sure would like to know the right way of doing it in plain ol' C.
Thanks to everyone who has commented - you guys are great :)
On your 32 bit machine, you're getting exactly what you expect. sizeof(tempVertices) is the size of the pointer, while sizeof(*tempVerices) gives you the size of a CGPint (probably two ints). You can't get the size of an allocated array with sizeof(). The value is only known at run-rime, and sizeof() is a compile time operator.
OK, after your edit I think I see what's going on. That code, exactly as you've written, should work OK. Xcode won't show you the values of any of those CGPoints, because it doesn't know it's an array, just a pointer to a single CGPoint. But it's there. Set a breakpoint right after you call setVertices:. At the gdb prompt, print some of those values.
(gdb) print _vertices[1]
$2 = {
x = 69,
y = 40
}
(gdb) print _vertices[3]
$3 = {
x = 17,
y = 10
}
Correct, see?
That's not to say there aren't issues here. For one thing, setVertices: is leaking that memory. You're allocating memory for tempVertices, holding onto that pointer, but not freeing it anywhere. The next time you call setVertices:, you'll have a leak.
A bigger issue is that nobody knows how many CGPoints are in that array, except the code that allocated the memory for it. Will it always be 4 CGPoints? What happens if somebody accesses _vertices[5] or _vertices[27]? Bad things, if you didn't allocate that much space for them.
Is there a requirement that this be a plain C array? Like, these points are going to get passed to OpenGL or cocos2d or something? If not, you might consider using some kind of array class for it. Because these aren't NSObject-derived objects you're storing, you can't use an NSArray. You could use a std::vector, if you don't mind dragging in a buncha C++. I probably would not do that.
If you're set on sticking with a C array, you should probably do some work to try to make the interface less error prone. Like I mentioned before, you'll need to track the size of the array. Perhaps you could add a parameter to setVertices: representing the number of CGPoints that the array holds. Then other parts of the code that access _vertices could check that to make sure they're not walking off the end of the array. And, like I mentioned before, make sure you free that memory before you reassign the pointer.
Messing about with pointers is fraught with danger. Tread carefully, there be dragons there.
The malloc is allocating enough space for 4 GCPoint structs and returning a pointer to the allocated space.
The first is at tempVertices + 0. It's tempVertices[0].
The second is at tempVertices + 1. It's tempVertices[1].
The third is at tempVertices + 2. It's tempVertices[2].
The fourth is at tempVertices + 3. It's tempVertices[3].
I would not use sizeof() to determine the size of an array allocated at runtime.
Have you actually had trouble assigning new CGPoint objects into your array? Does CGPointMake() perform any allocation of its own?

Passing a pointer that is part of an object (Cocoa)

OK, I have a custom object (an NSManagedObject subclass, if it matters) and I want to pass a pointer to one of its iVars to a function that I've set up to modify such values. With a normal pointer you'd just prefix it with an ampersand (&) as in the classic NSError &error example, but that can't be done with dot notation. I can't just pass &object.iVar as I'd hoped. Can anyone suggest a simple and elegant way to obtain the pointer of iVar so that I can pass it? I am loath to pass the entire object for reasons of code structure and neatness.
-Ash
Argh, as is almost always the case, I ask a question after an hour of frustrating puzzling then ten minutes later answer it myself. I don't know, maybe asking questions is some kind of therapeutic trigger for answers... shame this isn't a psychology website.
Anyway, my solution was to add a new 'pseudo-getter' method to the object I'm trying to access the pointer from that looks a bit like this:
- (Pointer **)getIVarPointer
{
return &iVar;
}
It's a bit cludgy, but since I only have that one iVar whose pointer I need to obtain it's not too bad. On ther other hand if there is a simpler, more 'official' way of doing this, I'd love to know it!

Creating pointer Attributes in cocos2d iPhone

I am working on a game. There are balls that fall from the top of the screen, and the player has to catch them, as the are caught they stack ontop of one another. I have a method that creates each new ball and adds it to an Array that i use to move the sprites. Problem is that the after they collide I need them to stop moving, since the array is called on to move them they all move. And if i try to make them stop they all stop. So I was hoping to create a pointer attribute if ther is such a think, for example "sprite.position" I need a new attribute that i can check like a boolean. I was hoping to create a attribute like sprite.hasCollided and if it returns YES then the ball should no longer move. Is this possible or is there a better way to do it?
Thanks
Tanner
I would suggest you create a ball object. And add the boolean as as part of the object.
CCNodes (and, by inheritence, CCSprites) have a userData property, which is a void*. You can use this to relate a custom object to a cocos2d object. Keep in mind if you use the userData option, you will, in most cases, need to allocate any memory when you create/assign the sprite, and release it when you are done.
int* myInt = (int*)malloc(sizeof(int));
*myInt = 0;
sprite.userData = myInt;
//some time later, when you are done with the sprite
free(sprite.userData);
As an improvement on the userData property, you can do what xuanweng suggests and create a ball object containing various game-related properties for the balls, and assign an instance of this to each of your ball CCSprites using the method above.

Storing a C struct in CFMutableDictionary

Since there is no counterpart to NSValue in Core Foundation, how are we supposed to store C structs in a CFMutableDictionary?
First, you can put an NSvalue in a CFMutableDictionary as-is, so the answer is "use NSValue." But I assume the rest of your question is "without using any Cocoa objects." In that case, just create a non-retaining CFMutableDictionary, and you can put any pointer you want into it. See "Defining Custom Collection Callbacks" for some example code. I use these a lot.
Remember that these still have to be pointers, so you're going to have to allocate your structs on the heap, not the stack. And that means that memory management is now your problem. Of course you could create a custom set of callbacks that do whatever you want, so if you're using boost or something else with its own ref-counting system, you can still implement that with CFMutableDictionary.
And of course you can replace the struct with a small data object. That's usually a lot easier. But different problems need different solutions.
CFMutableDictionary
CFDictionaryAddValue
A CFType object or a pointer value to add to the dictionary.
you just pass a pointer to your struct.