Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

spt

macrumors member
Original poster
Oct 27, 2009
39
7
I would like to build a simple interface around some c-code I have. I've spend over two hours now on a seemingly simple problem with Objective C.

It simply seems impossible to call an Objective C function from within a normal c function. If I do, for example:

void changeInfo()
{
[TextField setIntValue:test];
}

I get an error that says "Use of undeclared identifier 'TextField'". Whereas if this piece of code would be like this:

- (void) changeInfo
{
[TextField setIntValue:test];
}

... it would work perfectly fine.

What am I doing wrong...?
 
Your 'TextField' variable isn't global—it's an instance variable of your class.

Objective-C methods have two implicit parameters that you don't see directly in the code: 'self' (a pointer to the object the method is called on) and '_cmd' (the selector of the method being called). When you access 'TextField', the code that gets generated is actually 'self->TextField'.

In a plain C function, there can be no implicit parameters, so even if your C function is defined inside your @implementation, it won't be able to find 'TextField', because it doesn't even know what 'self' is.

One thing I often do is just make an explicit 'self' parameter in plain C functions, and then access the ivars explicitly with 'self->TextField'. The compiler won't complain about @private or @protected ivars as long as the function definition is within the @implementation of your class.
 
Is TextField an iVar? If so, it should be textField because the leading character should only be caps if it's a Class name, not an instance of a class.

The issue you're having is one of the scope of your variables. In your function example, since you haven't passed in a reference to your textField object, your code won't be able to access it. For example, this should work:
Code:
void changeInfo( NSTextField *aTextField )
{
     [aTextField setIntValue:test];
}

Whereas the method version will work if "aTextField" is declared as an ivar of the Class you're working in. All instance methods have access to the ivars of the instances of their class.
 
Thanks a lot for your comments, it now works!

Code:
void changeInfo( NSTextField *aTextField )
{
     [aTextField setIntValue:test];
}

Using a global did the trick.

The above suggestion would be quite complex in this specific case, as the c-program involves starting a lot of threads using the pthread library. The thread functions thus can't easily be started with an argument.
 
The above suggestion would be quite complex in this specific case, as the c-program involves starting a lot of threads using the pthread library. The thread functions thus can't easily be started with an argument.

The function prototype for pthread_create():
Code:
     int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void
                        *(*start_routine)([COLOR="Blue"]void *[/COLOR]), [COLOR="Red"]void *arg[/COLOR])
The blue-hilited part declares that start_routine is a function with a single parameter, whose type is pointer-to-void. The red-hilited parameter is the actual argument value to pass to the function.

From the man-page for pthread_create():
The thread is created executing start_routine with arg as its sole argument.​
 
Thanks a lot for your comments, it now works!

Code:
void changeInfo( NSTextField *aTextField )
{
     [aTextField setIntValue:test];
}

Using a global did the trick.

The above suggestion would be quite complex in this specific case, as the c-program involves starting a lot of threads using the pthread library. The thread functions thus can't easily be started with an argument.

Reading up on "blocks" and "Grand Central Dispatch" will safe you an awful, awful lot of headaches. Us as well. :D
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.