4

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.

anotherCoder
  • 712
  • 3
  • 11
  • 25
  • you can do that ... but you need a reference to `self`. the c function is not part of the object .. so it does not know what `self` is. – Bastian Oct 12 '12 at 07:32
  • Could you be a little more specific? I can do which one of the 2?? Calling objective c function from a C function? or Creating a UIButton from a C function?? – anotherCoder Oct 12 '12 at 07:38
  • 1
    If you have an existing instance of `ViewController`, that will be creating a completely new instance, which is likely not what you want. Please describe in broad terms what you're trying to accomplish. If `abc()` is a callback function whose signature can't be changed, where is it defined and what does it do? Is the `ViewController` instance the object who set up the callback function? – NSGod Oct 12 '12 at 08:09
  • sometimes when you give a c function as a callback, it gives you a `void*` argument to pass your own data into your implementation. Why is that not the case here/what does the C library do? The only way to get around this otherwise would be using a global variable (which is almost never the answer.) – tehwalrus Oct 12 '12 at 08:34

3 Answers3

5

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;
}
NSGod
  • 22,699
  • 3
  • 58
  • 66
  • Yes this could be a solution, but in my case, I can't change the signature of the C function **abc** as its a callback function getting assigned elsewhere. – anotherCoder Oct 12 '12 at 07:57
  • Can you describe in broad level terms what you're trying to accomplish? – NSGod Oct 12 '12 at 08:02
  • 1
    @Vinu: updated my answer based on results you're obtaining in your other question... – NSGod Oct 12 '12 at 16:32
  • Thank you, @NSGod. The code + example + explanation makes it very clear. But only one doubt remains, is this the most efficient way? or is it the only way?? if its the latter, is it okie to use it in an app. – anotherCoder Oct 13 '12 at 05:27
1

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.

tehwalrus
  • 2,589
  • 5
  • 26
  • 33
  • http://stackoverflow.com/questions/12856000/objective-c-uibutton-not-displayed this is how i am using it. – anotherCoder Oct 12 '12 at 09:27
  • my answer also works for that question, but I'm fairly sure it's against the guidelines for me to just copy and paste it over there. You still need to access the relevant `ViewController` from arbitrary scope, this is the way/one way to do that. – tehwalrus Oct 12 '12 at 10:16
  • @tehwalrus: It's the same exact question as this one. You have the right idea about the global variable, though there shouldn't be any need to make it a class method... – NSGod Oct 12 '12 at 16:19
  • @NSGod agreed, repost. The class method provides security (given that we want a `static` rather than a real global variable,) and the reason the static method is required is that the OP said they wanted, ideally, to be able to move the c function out of the class implementation file - the static method lets them do that (and encapsulates it nicely.) – tehwalrus Oct 12 '12 at 16:39
0

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.

Seg Fault
  • 1,331
  • 8
  • 16