How to handle an array of pointers in Objective-C - c

I figured out the answer to this question, but I couldn't find the solution on here, so posting it for posterity.
So, in Objective-C, how do you create an object out of a pointer in order to store it in objective-c collections (NSArray, NSDictionary, NSSet, etc) without reverting to regular C?

NSValue *pointerObject = [NSValue valueWithPointer:aPointer];
This will wrap the pointer in an NSValue. To get it back out later use NSValue's instance method (pointerValue:)

An alternative solution is to define a class that has methods that access/manipulate the contents of the pointer, then add instances of that to the array.
Don't bother subclassing NSValue as it really adds nothing to the solution.
Something like:
#interface FooPtr:NSObject
{
void *foo;
}
+ fooPtrWithFoo: (void *) aFoo;
.... methods here ...
#end
I specifically chose an opaque (void *) as that tells the client "don't touch my innnards directly". In the implementation, do something like #define FOOPTR(foo) ((Foo *) foo) Then you can FOOPTR(foo)->bar; as needed in your various methods.
Doing it this way also makes it trivial to add Objective-C specific logic on top of the underlying datatype. Sorting is just a matter of implementing the right method. Hashing/Dictionary entries can now be hashed on foo's contents, etc...

Related

Shared pointer in rust arrays

I have two arrays:
struct Data {
all_objects: Vec<Rc<dyn Drawable>>;
selected_objects: Vec<Rc<dyn Drawable>>;
}
selected_objects is guarenteed to be a subset of all_objects. I want to be able to somehow be able to add or remove mutable references to selected objects.
I can add the objects easily enough to selected_objects:
Rc::get_mut(selected_object).unwrap().select(true);
self.selected_objects.push(selected_object.clone());
However, if I later try:
for obj in self.selected_objects.iter_mut() {
Rc::get_mut(obj).unwrap().select(false);
}
This gives a runtime error, which matches the documentation for get_mut: "Returns None otherwise, because it is not safe to mutate a shared value."
However, I really want to be able to access and call arbitrary methods on both arrays, so I can efficiently perform operations on the selection, while also being able to still perform operations for all objects.
It seems Rc does not support this, it seems RefMut is missing a Clone() that alows me to put it into multiple arrays, plus not actually supporting dyn types. Box is also missing a Clone(). So my question is, how do you store writable pointers in multiple arrays? Is there another type of smart pointer for this purpose? Do I need to nest them? Is there some other data structure more suitable? Is there a way to give up the writable reference?
Ok, it took me a bit of trial and error, but I have a ugly solution:
struct Data {
all_objects: Vec<Rc<RefCell<dyn Drawable>>>;
selected_objects: Vec<Rc<RefCell<dyn Drawable>>>;
}
The Rc allows you to store multiple references to an object. RefCell makes these references mutable. Now the only thing I have to do is call .borrow() every time I use a object.
While this seems to work and be reasonably versitle, I'm still open for cleaner solutions.

When to use GBaseInitFunc

So I was reading glib manual Instantiable classed types: objects: GObject Reference Manual. I know that when I am creating my own class I should use GClassInitFunc to handle class initialization. Question is, when do I need to use GBaseInitFunc?
Not to be flip, but I think the answer is "extremely rarely." I've never had to use it.
This is a really good question though. I was curious so I did a code search. It looks like the majority of occurrences of GBaseInitFunc are just casting a null pointer to the correct function pointer type. Some others I don't understand what they are doing. Here's one that is used to keep track of how many classes are initialized from that base class (though the info doesn't seem to be used.)

How can this object reference itself

I've been tinkering with some code in a effort to understand OOP using c.
I really like this style and want to use it. The code sample works great if another class creates an instance of FooOBJ.
How can FooOBJ reference itself to change its own variables?
Do I need to make a copy of foo in the constructor or something like that or am I wandering away from the right way to use this methodology?
struct fooobj {
int privateint;
char *privateString;
};
FooOBJ newFooOBJ(){
FooOBJ foo=(FooOBJ)malloc(sizeof(struct fooobj));
bzero(foo, sizeof(struct fooobj));
return foo;
}
void setFooNumber(FooOBJ foo,int num){
if(foo==NULL) return; /* you may chose to debugprint something
*instead
*/
foo->privateint=num;
}
void setmyself(int val)
{
//this->privateint = val
}
Well, any function operating on an instance of your "class" will have to take a pointer to the instance. This happens automatically and implicitly in C++, but in C you'll have to pass a "this" pointer everywhere.
What this means is that your setFooNumber has the right signature for a "member function", whereas setmyself does not.
There's a reason C++ and other OO languages have an implicit parameter to instance methods. The only way this can be done is if you explicitly pass a this pointer. A function doesn't have access to something that isn't declared in an appropriate scope: locally or globally (parameters being local).
To understand OOP in C, you'll need to understand how to simulate pure OO code in a procedural way.

A std::tr1::shared_ptr for Objective C++ on iPhone?

I am mostly a C++ developer, recently I am writing iPhone applications.
The memory management on iPhone is OK to me, due to resource limitation, it's encouraged to use reference counters rather than deep copy.
One annoying thing is I have to manage the reference counters by myself: alloc means counter = 1; retain means counter++, release means counter--
I wish to write a shared_ptr like class for Cocoa Touch, so I rarely have to manually manipulate the reference counters by myself.
I doubt if there's any existing code for that, and I'd like to hear some advices, today is the 5th day since I started to learn objective c
Thanks.
As long as you learn the memory management rules first, there is no real problem with shared_ptr - it can help you in C++ contexts but doesn't let the ownership questions magically disappear.
shared_ptr supports a custom deallocator so the following:
#interface A : NSObject
- (void)f;
#end
#implementation A
- (void)dealloc { NSLog(#"bye"); [super dealloc]; }
- (void)f { NSLog(#"moo"); }
#end
void my_dealloc(id p) {
[p release];
}
// ...
{
shared_ptr<A> p([[A alloc] init], my_dealloc);
[p.get() f];
}
... outputs:
moo
bye
... as expected.
If you want you can hide the deallocator from the user using a helper function, e.g.:
template<class T> shared_ptr<T> make_objc_ptr(T* t) {
return shared_ptr<T>(t, my_dealloc);
}
shared_ptr<A> p = make_objc_ptr<A>([[A alloc] init]);
You forgot case 4
[4] you need to pass a pointer to an object out of a method as the return value.
This is where you need -autorelease.
I suggest you read the memory management rules and write some real code before you attempt this little project so that you can get a feel of how memory management is supposed to work.
Automatic reference counting, coming in iOS 5, will effectively make any pointer to an objective-c object act like a smart pointer. Retain/release calls will be synthesized by the compiler on assign and deallocation, unless you explicitly declare a reference to be weak, in which case they'll be automatically zeroed out when the object is deallocated.
My advice is to wait a couple of months for that. You might be able to put together something similar in the meantime, but I'd recommend against it. For one thing, it'll be ugly. Example:
smart_ptr<id> array = make_smart_ptr( [NSMutableArray array] );
NSUInteger count = [array count]; // won't work.
count = [array.get() count]; // works, but yuck.
[array.get() setArray: anotherArray.get()]; // even more yuck.
Also, if your headers are full of c++ classes, you'll have to compile your entire project in objective-c++, which may cause you problems as objective-c++ isn't 100% compatible with objective-c code, and not all third-party frameworks will work properly with it. And forget about sharing your code with anyone else.
It might be an interesting excercise to make something like this work, but you won't want to actually use it. And watch out for the temptation to recreate your favourite bits of C++ in Objective-C. The languages are very different, and you could spend a lot of time doing that, which is time not spent learning all the great stuff you can do in Objective-C that you can't do in C++.
Resource management in Cocoa can be tricky: some API calls automatically retain a reference and some don't, some return an autoreleased object, some a retained object. By shielding this in a shared_ptr class, you'll more likely to make mistakes. My advice is to first take the "normal" Cocoa route until you're fairly experienced.
Have you looked into [object autorelease]? Perhaps that would make things a bit easier.

Wrapping a C Library with Objective-C - Function Pointers

I'm writing a wrapper around a C library in Objective-C. The library allows me to register callback functions when certain events occur.
The register_callback_handler() function takes a function pointer as one of the parameters.
My question to you gurus of programming is this: How can I represent an Objective-C method call / selector as a function pointer?
Would NSInvocation be something useful in this situation or too high level?
Would I be better off just writing a C function that has the method call written inside it, and then pass the pointer to that function?
Any help would be great, thanks.
Does register_callback_handler() also take a (void*) context argument? Most callback APIs do.
If it does, then you could use NSInvocation quite easily. Or you could allocate a little struct that contains a reference to the object and selector and then cobble up your own call.
If it only takes a function pointer, then you are potentially hosed. You need something somewhere that uniquely identifies the context, even for pure C coding.
Given that your callback handler does have a context pointer, you are all set:
typedef struct {
id target;
SEL selector;
// you could put more stuff here if you wanted
id someContextualSensitiveThing;
} TrampolineData;
void trampoline(void *freedata) {
TrampolineData *trampData = freedata;
[trampData->target performSelector: trampData->selector withObject: trampData-> someContextualSensitiveThing];
}
...
TrampolineData *td = malloc(sizeof(TrampolineData));
... fill in the struct here ...
register_callback_handler(..., trampoline, td);
That is the general idea, anyway. If you need to deal with non-object typed arguments and/or callbacks, it gets a little bit trickier, but not that much. The easiest way is to call objc_msgSend() directly after typecasting it to a function pointer of the right type so the compiler generates the right call site (keeping in mind that you might need to use objc_msgSend_stret() for structure return types).

Resources