In my application, i have a mix of C++ and Objective C++ code, at one place, i need to insert pointer of c++ class object to NSMutableArray , but i am getting NSINvalidArgument exception,
Can anyone guide me, how can i insert void pointer to NSMuatableArray
This is what i have tried ,
pArray = [[NSMutableArray alloc]initWithCapacity:myList.size()];
Node *node = myList.getHead();
int idx =0;
void *ptr = nil;
while ( node ) {
[pCTArray insertObject:(NSObject *)node atIndex:idx];
node = node->getNext();
idx++;
}
Is there any otherway to insert it into the MutableArray,
the possible workaround i made is : having store index link this
[myArray insertObject:[NSNumber numberWithInt:idx] atIndex:idx];
and this array i would be using in all NSTable/NSOutliveVIew delegate method , i need to pick the index and get the element from the linklist, but worried because of performance, as too many function call would be needed,
Is this any bug in Cocoa or i am making anything wrong ?
NSArrays expect to hold objective-C objects conforming to the NSObject protocol. If you wish to wrap a pointer, use NSValue:
[myArray insertObject:[NSValue valueWithPointer:node] atIndex:idx];
You are manually responsible for all memory management of that pointer, as objective-C can't reference count it in the usual way.
NSMurableArray only accepts Objective-C objects (hence the argument type of addObject: being id).
Are you on the Mac or iOS? If you're on the Mac, You might want to look at NSPointerArray.
You might also be able to be CFMutableArray with custom callback functions, but I haven't tried this myself.
A third option is NSPointerArray.
Related
I have a QList and I'm trying to replace the objects in the list with new objects. The context is that I have a list of custom objects (the class name is "Conversation") to represent a list of group chats in a messaging platform. I use std::find_if to iterate through the list of pointers to find one with the right ID, and I want to take the pointer to that found object, deallocate it (delete?), and reassign that pointer to point at an object I generate with the "new" keyword. I think I'm doing this right but I'm not sure how to verify.
I tried a couple different iterations, ran into some issues where I realized I was using a const_iterator rather than just an iterator, so I couldn't modify any data. But I've fixed that and it seems like it's working, but I'm not positive.
Here's what I've got:
GroupChat *gc = new GroupChat(); // extends Conversation
// ...I update the member data here...
auto foundChat = std::find_if(conversations_.Conversations.begin2(),
conversations_.Conversations.end2(),
[this, gc](Conversation* o) { // my code to find the correct one...
}
if (foundChat != conversations_.Conversations.end()) {
auto c = (*foundChat);
delete c; // Is this right? Not positive...
//*foundChat = nullptr; // do I need this?
c = gc;
}
It seems like it's working but I'm worried about dangling pointers and incorrect memory deallocation/allocation. Could someone spot check me on this? Thanks for any help!
I don't know the real difference between this two macros in Cocos2d-x
CC_SAFE_DELETE and CC_SAFE_RELEASE_NULL
Can anyone explain it to me? It probably can solve a few memory leaks I have in my game.
Here is an example of where I want to use it.
CoolLayer * CoolLayer::create()
{
CoolLayer * pRep = new CoolLayer();
if (pRep && pRep->init() )
{
pRep->autorelease();
}
else
{
CC_SAFE_DELETE(pRep);
}
return pRep;
}
Thanks in advance.
CC_SAFE_DELETE is defined as
do { delete (p); (p) = nullptr; } while(0)
basically used for deleting usual c++ declared objects you want to remove.
CC_SAFE_RELEASE is defined as
do { if(p) { (p)->release(); } } while(0)
(edit just realized your question asks about CC_SAFE_RELEASE_NULL, its exactly the same except it also nulls out your pointer)
This will decrement the reference count of your cocos2d-x objects which is used by cocos2d-x's reference counting construct, if an object hits a reference count of 0 it will be de-alloced for you.
Use safe delete for standard c++ things like vectors or arrays or whatever your custom classes may be. Use safe release for anything to inherits from cocos2d::Object, as it has the native reference counting built in, making keeping track of your object references a little easier.
If you are unfamiliar with reference counting, it comes from the fact that cocos2d was originally created in objective-c, where reference counting is the norm, so after the port, they continued to use it for all their native objects.
I have a data structure defined up here called this:
typedef list <classSpec*> ClassSpecList;
I'm trying to add stuff into the list here based on functions that return certain values of that match the same data type. In one function, I have a list pointer object defined here and I have another statement that calls a function.
ClassSpecList *answer = 0;
classSpec *thisanswer = parseClass(br);
Basically I'm trying to add the results of what thisanswer returns into my main ClassSpecList. Problem is, when I try
answer->push_back(new classSpec (*thisanswer));
It compiles but I get a seg fault
When I try somethign else like:
answer->insert(ClassSpecList.begin(), *thisanswer);
I keep getting primary expression errors and I do not know why. I even tried it with other list made without typedef and I still get those.
Thank you.
You should initialize the pointer answer first, like :
ClassSpecList *answer = new ClassSpecList;
then you can add thisAnswer into this list.
This should work:
ClassSpecList *answer = new ClassSpecList;
answer->push_back(thisAnswer);
as should this, which is usually recommended:
ClassSpecList answer;
answer.push_back(thisAnswer);
If possible, parseClass shouldn't return a pointer, and you should use typedef list <classSpec> ClassSpecList;.
I have a bit of pure C++ code which is reading from Objective-C data structures with the help of a function pointer to a method in an Objective C class. I'm treating the Objective-C class instance to read from as an opaque pointer. For example, the C++ method that does the reading has a signature like this:
typedef void(*DataGetterFunc)(void * dataSource, int key, int * outValue);
...
void readData(void * dataSource, DataGetterFunc dataReadingFunc);
When I call the C++ method from Objective-C, I do the following:
MYDataStructure * objectiveCData;
cppObject->readData((__bridge void*)objectiveCData, DataGetterFuncImpl);
Finally, DataGetterFuncImpl dereferences the Objective-C class like so:
void DataGetterFuncImpl(void * dataSource, int key, int * outValue)
{
MYDataStructure * objCData = (__bridge MYDataStructure*)dataSource;
...
}
Originally in DataGetterFuncImpl I was using __bridge_transfer, but then I was getting EXC_BAD_ACCESS the next time ARC called retain on MYDataStructure, So I assumed it was being over-released by the use of __bridge_transfer and changed it to just __bridge.
Are there any memory leaks I should look for by just using __bridge, or do I need to use some combination of __bridge_retain and __bridge_transfer in this case?
When you're using __bridge to convert to or from objc, owership is just not affected. That means, that while you're using the object in C++ you must make sure that there's still a strong reference around.
If you, on the other hand, use __bridge_retain to convert to void* and __bridge_transfer to convert back to id (or any other retainable object type), you must make sure that each __bridge_retain is matched by exactly one __bridge_transfer later.
Here is a quick snippet of my code to parse PDB files for molecular dynamics simulations:
Structure *s = new Structure(pdb_filename);
Chain *c = new Chain();
while( ... read file ... ) {
if ( ... new chain ... ) {
Chain *c = new Chain();
s->add_child(c); // Add reference to a vector to
// save the Chain for later
}
}
When the containing function is called, the code acts as normal and gives brand new Structure and Chain objects as in the first two lines of the snippet.
When the criteria for a new chain is met again while looping over the file, the code returns the same Chain pointer to the object as before.
Will g++ give the same pointer over and over? Is there any way to get around this?
If I add the c pointer to the 's' children vector, I assume calling delete c will cause even larger headaches?
Structure *s = new Structure(pdb_filename);
Chain *c = new Chain();
You just defined c here
while( ... read file ... ) {
if ( ... new chain ... ) {
Chain *c = new Chain();
You just defined c here again shadowing the other one.
When the criteria for a new chain is met again while looping over the
file, the code returns the same Chain pointer to the object as before.
Now which one of the two you're looking at?
I think you can see the problem already.
the code returns the same Chain pointer to the object as before
That is hard to believe.
Will g++ give the same pointer over and over?
No. Each time you call new Chain it's a different Chain. It's a different pointer, pointing to different memory (that's why it's new). It's also shadowing the c before the while.
new Chain() should give a different pointer each time
I think I may have an inkling what your problem is--
The c within your loop does not refer to the same variable as the c outside your loop. The c outside your loop will retain its same value all the way through.