Calling C++ from Objective-C

How can I call a C function from Objective-C

Just call setup(). As declared, is in no way tied to an object - it's just a regular C function.

How to call an Objective-C Method from a C Method?

In order for that to work, you should define the C method like this:

void cMethod(id param);

and when you call it, call it like this:

cMethod(self);

then, you would be able to write:

[param objcMethod];

In your cMethod.

This is because the self variable is a special parameter passed to Objective-C methods automatically. Since C methods don't enjoy this privilege, if you want to use self you have to send it yourself.

See more in the Method Implementation section of the programming guide.

How to call C function from Objective-C

Objective-C is a superset of C. All you need to do is call it from your Objective-C code.

 char* args[] = { "foo", "bar", NULL }; // Might need the NULL to emulate command line arguments.
int result = mainFunction(2, args);

You could pass argc and argv directly from your own main

 int main(int argc, char** argv)
{
int result = mainFunction(argc, argv);
}

If your arguments are in an array of NSStrings, you'll need to convert them to a normal C array of C strings:

char** cStringArray = malloc(([stringArray count] + 1) * sizeof(char*));
for (int i = 0 ; i < [stringArray count] ; ++i)
{
NSString* aString = [stringArray objectAtIndex: i];
cStringArray[i] = [aString UTF8String];
}
cStringArray[[stringArray count]] = NULL;
int result = mainFunction([stringArray count], cStringArray);
free(cStringArray);

It's a long time since I last did any Objective-C, so apologies for any syntax errors.

Calling C++ from Objective-C

Essentially you need an ObjC class with .mm extension that calls an ObjC class with .mm extension. The second one will be used as a C++ wrapper class. The wrapper class will call your actual .cpp class. It's a little tricky, so I'm going to give you some verbose code. Here is an overview of the project:

Sample Image

In your ObjC code (ViewController) you would call the CplusplusMMClass

- (IBAction)buttonPushed:(UIButton *)sender {
self.mmclass = [[CplusplusMMClass alloc]init]; // bad practice; but showing code
NSString *str = [self.mmclass fetchStringFromCplusplus];
[self populateLabel:str];
}

Here is the CplusplusMMClass .h and .mm

#import <Foundation/Foundation.h>
#import "WrapperClass.h"

@interface CplusplusMMClass : NSObject
@end

@interface CplusplusMMClass()
@property (nonatomic, strong) WrapperClass *wrapper;
- (NSString*)fetchStringFromCplusplus;
@end

#import "CplusplusMMClass.h"
#import "WrapperClass.h"

@implementation CplusplusMMClass

- (NSString*)fetchStringFromCplusplus {
self.wrapper = [[WrapperClass alloc] init];
NSString * result = [self.wrapper getHelloString];
return result;
}

@end

Here is WrapperClass .h and .mm

#ifndef HEADERFILE_H
#define HEADERFILE_H

#import <Foundation/Foundation.h>

#if __cplusplus

#include "PureCplusplusClass.h"

@interface WrapperClass : NSObject
@end

@interface WrapperClass ()
- (NSString *)getHelloString;
@end

#endif
#endif

#import "WrapperClass.h"

#include "WrapperClass.h"
#include "PureCplusplusClass.h"

using namespace test;

@interface WrapperClass ()
@property (nonatomic) HelloTest helloTest;
@end

@implementation WrapperClass

- (NSString *)getHelloString {
self.helloTest = *(new HelloTest);
std::string str = self.helloTest.getHelloString();
NSString* result = [[NSString alloc] initWithUTF8String:str.c_str()];
return result;
}

@end

Here is the PureCplusplusClass .h and .cpp

#ifndef __HelloWorld__PureCplusplusClass__
#define __HelloWorld__PureCplusplusClass__

#include <stdio.h>
#include <string>

using namespace std;

namespace test {
class HelloTest
{
public:
std::string getHelloString();
};
}

#endif /* defined(__HelloWorld__PureCplusplusClass__) */

#include <stdio.h>
#include <string>

std::string test::HelloTest::getHelloString() {
std::string outString = "Hello World";
return outString;
}

This code is not perfect! I'm having trouble with the namespace test being recognized. I'll update when I can.

But this should get you there!!!!

Pure C function calling Objective-C method?

After much experimenting, I found that the most elegant way of solving my problem was to turn my core C library into an NSObject using the .m suffix. The method of calling back and forth resolved instantly. This change DOES alter my original library, but by so little, it's manageable. So to review:

My original C file was renamed to use the .m suffix. Then I added

@interface myCLibrary : NSObject

@end

to my .h file, and added to my formerly .c file, now renamed .m.

@implementation myCLibrary

@end

Just remember that C functions aren't to be pasted between these interface / implementation declarations, below them. Only Objective-C is to go inside these statements. Once I did that, calling the C functions, and calling BACK to other C functions worked great.

Thanks for all the help regardless.

Calling C from Objective C

The last compiler error happens because mt_lrand(); returns an int, not a pointer to an int. Therefore, the last line should be

uint32_t i = mt_lrand();

All the other errors are due to the fact that you did not #include the library header. Could you please post the errors that occur when you do include the library header?

Call objective-c method from C library

You can absolutely call Objective-C methods from C functions. To do so, however, you will need to make sure that your C function has a reference to an Objective-C object of some kind. Your example above doesn't show that.

So, you might write your function as:

int doStuff(id ref, char* aString) {
[ref objcMethod];
....
return 0;
}

Or maybe you would store the ref in static storage in your library, so that it was available to all functions, without passing it explicitly. It really depends on your use-case. Remember that Classes are objects, too, in Objective-C; so if you need ref to be a class (for a static methods), that can work, too.

There is a tangential topic. Sometimes, in Objective-C you want a direct reference to a method implementation so that you can invoke it directly. This is handy in tight loops, where performance is required. If this is your need, this blog post goes into the topic.

Calling Objective C from C

You need to provide the callback function with a pointer to the view containing the label and some means of updating it. All callback functions should have a context pointer of some sort which can hold information allowing them to perform context-specific actions. If you cannot change the callback function semantics then you are stuck I'm afraid, however if you can, do it something like this:

void cfunc(const char *labelUpdateText, void *contextInfo) {
YourView *view = (YourView *)contextInfo;
[view updateLabelWithText:[NSString stringWithUTF8String:labelUpdateText]];
}

You will need to provide the updateLabelWithText method in YourView and if you are using ARC there will be some bridging to do as well during the casting of contextInfo (the compiler will help you there though).

From Objective C call C++

It's not possible to call C++ functions from plain Objective-C (like you can't call C++ from plain C).

You can convert your Objective-C file to Objective-C++, though. To do so, just rename the file to use the extension .mm instead of .m.

C function calling objective C functions

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;
}


Related Topics



Leave a reply



Submit