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:
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
C++: How to Check If the Cin Buffer Is Empty
Qt "Private Slots:" What Is This
C++11 Compiler: Closest to the Standard and How Close
Is There Any G++ Option to Dump Class Layout and Vtables
Compile Program for 32Bit on 64Bit Linux Os Causes Fatal Error
Get Local Ip-Address Using Boost.Asio
Convert First Letter in String to Uppercase
How Can Boost::Serialization Be Used with Std::Shared_Ptr from C++11
How Far to Go with a Strongly Typed Language
Print Template Typename at Compile Time
Print MACro Values Without Knowing the Amount of MACros
Setting Width in C++ Output Stream
C++ Specialization of Template Function Inside Template Class
Is Shrink_To_Fit the Proper Way of Reducing the Capacity a 'Std::Vector' to Its Size