I'm trying to figure out how to call a c function from an obj-c file. I've seen some good examples of how to do the opposite.
In the example below I have an objective c file. It contains a c function named setup.
I want to be able to create an instance of my obj-c file in the regular way and then call the setup function.
Header
#import <Foundation/Foundation.h>
void setup(int,float);
#interface Test : NSObject {
}
#end
Source
#import "Test.h"
#include <stdio.h>
#include <stdlib.h>
void setup(int val1,float val2)
{
//do something with values
}
#implementation Test
#end
View did load
Test *test =[Test alloc]init]
//this does not work
test.setup(6,1.4);
Just call setup(). As declared, is in no way tied to an object - it's just a regular C function.
Related
I have summarized the steps of the problem, I have a C function defined in Objective-C:
ObjC.h
#import <Foundation/Foundation.h>
void cuslog(NSString *format, ...);
#interface ObjC : NSObject
#end
ObjC.m
#import "ObjC.h"
#implementation ObjC
#end
void cuslog(NSString *format, ...)
{
// Implementation
}
I exposed it in Bridging-Header.h:
#import "ObjC.h"
// Also tried to put this line in bridging header
void cuslog(NSString *format, ...);
In Swift I intend to call the function like this:
cuslog("Some log")
But the error says:
"Use of unresolved identifier 'cuslog'"
What is the correct way to call the function in Swift?
According to the Swift devs, C variadic functions are not compatible with Swift variadics, so you won't be able to call your function directly.
The only workaround at this time is to write a non-variadic wrapper in C or Obj-C, and call that from Swift.
I want to create a class that will contains static values accessable from all project.
Pseudocode:
class Constants:
constant String API_URL : "http://api.service.com"
constant Integer SOME_VALUE : 7
How can I do this with Objective-C ?
Answer for your question is extern keyword . I will explain it to you using an example . Add objective c classes your project and name them Common , Now in Common.h
#interface Common : NSObject
extern NSString *SiteApiURL;
#end
After you defined an instance of NSString Class using the extern keyword what you need to do is switch to Common.m class and initialize the value for NSString (SiteApiURL)
#import "Common.h"
#implementation Common
NSString *SiteApiURL = #"http://api.service.com";
#end
Import the Common.h class within the project-Prefix.pch file like this
#import <Availability.h>
#ifndef __IPHONE_3_0
#warning "This project uses features only available in iOS SDK 3.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "Common.h"
#endif
All done , now you can use the object "SiteApiURL" anywhere in the whole project and you need not to import any class anywhere i.e. You can use this variable anywhere in the project directly.
You could do it using preprocessors:
#define API_URL #"http://api.service.com"
#define SOME_VALUE (7)
Accessing defines would be simple: [object do:API_URL];
Or you could use constants
NSString * const apiURL = #"http://api.service.com";
NSNumber * const someValue = #7;
Accessing consts would be like accessing variables, So the string would just be a simple call. The NSNumber is an object wrapper for primitives so you'd need to access it like: someValue.intValue
You can create a Singleton with all necessary constants Here is a sample
If you do not want to create the class than you can use static private variables and static getters.
#interface
+(NSString*) getValue;
#end
#implementation
static NSString *_value = #"....";
+(NSString*) getValue {
return _value;
}
#end
I had to implement a C function in an Objective-C class that normally would get called with int main (in it's own file). Since I'm unfamiliar with splicing code I need to know how to have it called upon in either the awakefromnib or applicationDidFinishLaunching from within the Cocoa section. Or if there's a much better way to do this I'm listening.
Here's an example without getting too technical:
// Cocoa Imports
#import "AppDelegate.h"
...
// C Inlcudes
#include <stdio.h>
// (int main had to change to something else obviously)
int dos () {
printf ("I'm a C program\n");
}
// (back to cocoa)
#implementation AppDelegate
#synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
//[This is where I need my C function above to execute]
It's called just the same as you would from C and you can call any C function you like:
// Cocoa Imports
#import "AppDelegate.h"
...
// C Inlcudes
#include <stdio.h>
// (int main had to change to something else obviously)
int dos (const char *filename)
{
printf ("I was passed '%s'\n", filename);
}
// (back to cocoa)
#implementation AppDelegate
#synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
dos("/path/to/some/file");
}
I'm trying to run through all the Objective C I possibly can as fast as I can for my new job. I've divided up my training so I do 1/2 with cocoa tutorials and I thought it also made sense to try to learn Objective C from a general perspective as well so the other 50% i'm trying to learn out of the "Programming In Objective C" book by Stephan Kochan (2004). Many of his examples up through the first 50 pages or so seem to imply that there is a way to make a simple class (interface, implementation, and main) all in the same file. I have been trying to compile this in the mac Snowleopard terminal for the sake of speed, but as soon as I call a method inside the main I get compile errors.
I know its not my gcc compiler because the file will compile, and I can even write a printf statement, but as soon as I try to call a method, I get compile errors. I would appreciate it if someone could demonstrate a simple inclusive objectivec.m file that actually works with a method call.
here's my code
#import <stdio.h>
#import <objc/Object.h>
#interface testing1 : Object
{
int number;
}
-(void) setNum:(int)a;
-(void) print;
#end
#implementation testing1;
-(void) setNum:(int) a{
number = a;
}
-(void) print{
printf("this is the number %i \n", number);
}
#end
int main(int argc, char* argv[] )
{
//testing1 *test =[testing1 new];
//[test setNum: (int)34];
printf("testing");
//[test print];
}
this will compile in the terminal with --- gcc tester1 -o myProg -l objc
I've tried to call those methods several different ways but it does not work
any help is appreciated. Perhaps I need to break it up and use make - I don't know
Thanks
MIke
You have ; at the end of #implementation -
#implementation testing1; // Semi colon shouldn't be present at the end
With that modification made, you should see the result. Online result of the program
[test setNum: (int)34];
Here typecasting 34 to int is unnecessary. You can just pass the message setNum to reference test with 34 followed by colon.
[test setNum:34 ];
Interface declarations should go in header while the implementation to source files. Only source files get compiled. Before even the compilation phase, pre-processor just copies the content of all imported files to the translation units. So,
testing.h
#import <Foundation/NSObject.h>
#interface testing1 : NSObject
{
int number;
}
-(void) setNum:(int)a;
-(void) print;
#end
testing.m
#import <stdio.h>
#import "testing.h"
// You should definitely import just stdio.h header here because of printf function usage
// testing.h also to be imported or else compiler doesn't know what is testing1.
#implementation testing1
-(void) setNum:(int) a{
number = a;
}
-(void) print{
printf("this is the number %i \n", number);
}
#end
main.m
#import <stdio.h>
#import "testing.h"
int main(int argc, char* argv[] )
{
testing1 *test =[testing1 new];
[test setNum: 34];
printf("testing");
[test print];
return 0;
}
Now you need to compile the two source files from which corresponding object files are generated. Linker combines these object files to give the final executable.
gcc -o test testing.m main.m -framework Foundation
Run -
./test
The book you're following is out of date. The Object class was effectively deprecated way back in 1994 with the introduction of OpenStep.
In Objective-C 2.0, the Object class simply isn't available at all. That's why your program produces compiler warnings/errors.
You should instead subclass NSObject and import <Foundation/Foundation.h>. Use the -framework Foundation gcc parameter, instead of -l objc.
First of all, you used #import <stdio.h>. You only need that when your using C only. Delete the sentence and use this instead.
#import <Foundation/Foundation.h>
Secondly, why are you using #import <objc/Object.h>? The "<" and ">" are only for frameworks. If you want to import another file you made, use #import "Object.h" instead. (Unless you're talking about NSObject, then you don't need to import anything because it is part of the Foundation framework.)
And lastly, you should take away the semicolon after the #implementation because it's unnecessary.
I have the following objective-C++ header with the simple method to return this pointer.
#interface MyObj
{
MyCPPObj * cpp;
}
-(MyCPPObj *) getObj;
I have created the simple method
#implementation MyObj
-(MyCPPObj *) getObj
{
return cpp;
}
Everything seems to work until I actually try to use the object in another file
newObj = [createdMyObj getObj];
It complains: error: cannot convert 'objc_object*' to 'MyCPPObje *' in initialization.
It seems that the method is return an objective-c object, but I specifically requested a C++ pointer.
MyCPPObj is an honest C++ class:
class MyCPPObj
{
public:
int x;
}
How can I fix that?
On my 10.6.3 machine, the following combination worked without any problem: aho.h
#import <Foundation/Foundation.h>
class MyCPPObj{
};
#interface MyObj:NSObject
{
MyCPPObj * cpp;
}
-(MyCPPObj *) getObj;
#end
and aho.mm
#import <Foundation/Foundation.h>
#import "aho.h"
void foo(){
MyObj*objcObj=[[MyObj alloc] init];
MyCPPObj*cppObj=[objcObj getObj];
}
Two pitfalls you might have fallen into:
Unlike C++, a class in Objective-C which doesn't inherit from NSObject won't work. (Well, you can make it work, but you don't want that usually.) Note the line #interface MyObj:NSObject.
To use NSObject, do #import <Foundation/Foundation.h>
Don't forget to use the extension .mm for Objective-C++ files.
Most likely you have forgotten to #import the header file with the #interface into the .mm file where you use getObj.
The error states what happens, and JeremyP is right on the money. When you forget to include a header file with the prototypes of the selectors, the compiler assumes the selector returns an object of type id. Well id is a typedef to objc_object*, which is incompatible with your C++ class. To fix the error, you simply need to include your header file in the file where you called getObj.