anotherCoder
anotherCoder

Reputation: 732

C function calling objective C functions

I've a c function in my viewController.m.

int abc(int a, char* b)
{
//do something
}

I also have a function

-(void) callIncomingClass
{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

    //set the position of the button
    button.frame = CGRectMake(100, 170, 100, 30);

    //set the button's title
    [button setTitle:@"Click Me!" forState:UIControlStateNormal];

    //add the button to the view
    [self.view addSubview:button];
}

Now I want to call callIncomingClass from within the function abc now.

How do you suggest I go about it??

Why I want to call an Objective C method from the C function is, I've cannot create a button or do some processing like that in the C function.

Should the following code work :

int abc(int a, char* b)
{ 
    ViewController * tempObj = [[ViewController alloc] init];
    [tempObj callIncomingClass];
}

edit : the big picture of what I am doing There is a c library, i.e. a library.c and library.h file. The library.h file has a struct that has callback functions. These need to be assigned with function pointers. so I've a c function with the signature int abc(int,char*) that is to be assigned to the callback function in the struct.

This function abc is defined in ViewController.m. Ideally i wanted it to be defined in a separate file. but this is also okie.

So now, the callback event happens, I want to create a UIButton with some action on the View. As I can't create a UIButton from a c function, i am calling a objective C method of the ViewController class, that creates the UIButton.

Hope that clears the picture as to how I am planning to use this.

Upvotes: 4

Views: 2375

Answers (3)

NSGod
NSGod

Reputation: 22948

Your button doesn't show because of what others and myself were saying: you need the existing instance of the ViewController. You are creating an entirely new instance of the ViewController, which is never brought on screen or pushed, etc.

You can accomplish what you need to do by using a global variable that points to your existing instance.

Here's what your .m should look like:

#import "ViewController.h"

static ViewController *viewController = nil;

@implementation ViewController

- (id)init {
    if ((self = [super init])) {
         viewController = self;
    }
    return self;
}

- (void)dealloc {
    viewController = nil;
}

-(void) callIncomingCreateButton {
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    //set the position of the button
    button.frame = CGRectMake(100, 170, 100, 30);
    //set the button's title
    [button setTitle:@"Click Me!" forState:UIControlStateNormal];
    //add the button to the view
    [self.view addSubview:button];
}

- (IBAction)DemoCall:(id)sender {
    callIncoming(1, "a");
}

@end

int callIncoming(int a, char* b) {
    [viewController callIncomingCreateButton];
    return a;
}

Upvotes: 5

tehwalrus
tehwalrus

Reputation: 2659

You need to get access to the correct ViewController* / instance, not any old one. If your C function signature doesn't let you pass in some arbitrary data via a void* or similar, then you need to use a class method, and a static variable to hold the temporary pointer as follows.

In your Objective C file:

static ViewController* cLibReceiver = NULL;

+(void) callIncomingClassOuter {
    [cLibReceiver callIncomingClass];
}

-(void) beforeTriggerCLibrary {
    cLibReceiver = self;
}

and in your (different) Objective C file with abc() in:

int abc(int a, char* b)
{ 
    [ViewController callIncomingClassOuter];
}

Where you trigger the C Library, you need to do this:

[theViewController beforeTriggerCLibrary]; // could be self, depending on context

c_library_call();

// optionally set cLibReciever back to NULL.

note: I may have got some of the syntax wrong on method headers etc, I'm not entirely familiar with objective C calling conventions. class methods are definitely + though.

note 2: you may not be allowed to extend the system class like this - you may need to define your own subclass. Again, not familiar enough with Objective C.

Upvotes: 1

Seg Fault
Seg Fault

Reputation: 1351

Assuming that you are in an Objective-C source file, calling an Objective-C function from a C function works exactly the same as calling the Objective-C function from any other Objective-C function. In either case, if you have a pointer ptr to the object that you want to call the function on, you write

[ptr callIncomingClass];

so of course in either case you need to somehow have the pointer to the object you want to call the function on. If you are in an Objective-C function (i.a. an instance method) the usual "source" for such pointers are (a) the implicit "self" pointer when you are calling a method on the same object as the currently running methid, (b) some instance-variable of the object on which the currently running method was called, (c) an argument to the currently running function or method, (d) a global variable or the result of some other function call. In plain C you can use (c) and (d), but not (a) and (b) because you don't have a self.

Upvotes: 0

Related Questions