user139816
user139816

Reputation: 214

Mixing C with Objective C

I'm a little confused as to whats going on in this snippet of example code. I am creating a property called 'processingGraph' of C struct 'AUGraph'. I then pass this struct to the Objective C method with [self createAUGraph:_processingGraph];

I then take this argument... - (void) createAUGraph:(AUGraph) graph { NewAUGraph (&graph); ... and create the struct.

However this does not seem to create the struct at the property name '_processingGraph' as I think it should.

Why is this? By passing in a struct to an objective C method, does it just create a copy? Which case, how would I pass a reference to a struct in a method?

Full code:

@interface AudioStepper ()
@property (readwrite) AUGraph processingGraph;

@end

@implementation AudioStepper

- (id) init{
if (self = [super init]) {
    [self createAUGraph:_processingGraph];
}
return (self);
}
- (void) createAUGraph:(AUGraph) graph {
NewAUGraph (&graph);
CAShow (_processingGraph); //no struct?
}

@end

Upvotes: 2

Views: 288

Answers (2)

BergQuester
BergQuester

Reputation: 6187

graph is not a pointer in your method, so it is getting copied to a new memory location, apart from the original variable. It is like passing in an int or float. This is what is called passing by value.

The C method, however, is using pass by reference. It takes the pointer to graph rather than copying the value.

Since this is an ivar, you can access the pointer to _processingGraph directly:

- (void) createAUGraph {
    NewAUGraph (&_processingGraph);
    CAShow (_processingGraph);
}

Or, if you need to pass in different graphs at different times, you want the method to take a pointer to an AUGraph, use pass by reference:

- (void) createAUGraph:(AUGraph*) graph {
    NewAUGraph (graph);     // Since graph is now a pointer, there is no
                            // need to get a pointer to it.
    CAShow (_processingGraph);
}

And call the method like so:

[self createAUGraph:&_processingGraph];

While that fixes the arguments, be sure to read danh's answer below for a better way to create structs.

Upvotes: 3

danh
danh

Reputation: 62686

I see that you've accepted an answer. Glad it's working. While you were accepting, I was composing this advice, which I think is still good advice....

Take a hint from the objective-c CG structs, like CGPoint, and define your structures this way:

// I've made up an AUGraph, since I don't know what yours looks like

typedef struct {
    // whatever is in here, say it's two ints
    int foo;
    int bar;
}AUGraph;

Make your properties assign...

@property (assign, nonatomic) AUGraph processingGraph;

And, most importantly, declare your creation function this way. (This will be quicker, and read more like the other library functions...

static inline AUGraph AUGraphMake(int foo, int bar) {
    AUGraph aug;
    aug.foo = foo;
    aug.bar = bar;
    return aug;
}

Here's how a printing function might look...

static inline NSString *NSStringFromAUGraph(AUGraph g) {
    return [NSString stringWithFormat:@"AUGraph: foo=%d, bar=%d", g.foo, g.bar];
}

Not it looks and feels like native stuff...

self.processingGraph = AUGraphMake(3,4);
NSLog(@"%@", NSStringFromAUGraph(self.processingGraph));

Upvotes: 2

Related Questions