libobjc: Calling a ObjC method from plain C? - objective-c

I am currently experimenting with the V programming language and looked at a few fun things I wanted to try out. One of the things that I wondered was, if I could call Objective-C methods from plain C without compiling a single .m file.
Since Python can do it with pyobjc, I wonder if I could make it work in V?
Imagine the following, very crude code:
#implementation Foo
- (id) greet: (char*)me {
printf("Hello %s!", me);
}
#end
Now, I know that with objc_sendMsg I can send messages - but how do I create the proper instance first?

It's going to look something like this:
Class fooClass = objc_lookUpClass("Foo");
id obj = class_createInstance(fooClass, 0);
SEL initSelector = sel_registerName("init");
((id (*)(id, SEL))objc_msgSend)(obj,initSelector);

Related

How to call Obj-c initializer class method with no params from Swift

I have a class in Obj-C, it can only be initialized by calling +new, and -init is not supported:
#interface SetupMainController : UIViewController
+(SetupMainController *)new;
-(id)init __attribute__((unavailable("Must use +new")));
#end
I am trying to run the following equivalent obj-c code in swift:
SetupMainController *setupController = [SetupMainController new];
[self presentViewController:setupController animated:YES completion:nil];
like so:
let sc : SparkSetupMainController = SparkSetupMainController.new()
or:
let sc : SparkSetupMainController.new()
or:
let sc : SparkSetupMainController()
(which obviously tries to call -init which is prohibited)
all fails,
getting "expected member name following '.'" error.
I found answers like this or this or apple docs but none give a straight answer how to do that simple task in Swift.
Help appriciated
If you change newin your Objective-C class to:
+(id)mynew;
Then suddenly all works:
var s: SetupMainController = SetupMainController.mynew()
Don't know why you cannot override +new. Maybe it's because is a class method?
EDIT: To add more mystery to this question, if you look up new in Apple's doc is defined in Swift using:
class func `new`() -> Self!
Do the backticks mean something like "this is reserved"?
EDIT 2: Looks like new doesn't work at all with Swift
This code does not compile:
let j = NSNumber.new()
var s = NSString.new()
EDIT 3:: SOLUTION
new is a reserved keyword in Swift, so to call +new() you need to add the back ticks:
let string = NSString.`new`()
Kudos to this answer

Convert a selector to its class_addMethod() encoding at compile time

I have the following Objective-C code in a testing harness for some crazy low-level code (don't ask):
/* This category is declared here but not defined anywhere.
* It lets me write
* id MyNewClass = objc_lookUpClass("MyNewClass");
* [MyNewClass class_method];
* without spurious compiler warnings.
*/
#interface NSObject (MyNewClass)
+(void) class_method;
+(void) class_method_taking_int: (int) f;
-(int) method_returning_int: (int) i;
#end
...
{
Class MyNewClass = objc_allocateClassPair([NSObject class], "MyNewClass", 0);
Class MyNewClass_meta = object_getClass(cls);
class_addMethod(MyNewClass_meta, #selector(class_method),
(IMP)..., "v#:");
class_addMethod(MyNewClass_meta, #selector(class_method_taking_int:),
(IMP)..., "v#:i");
class_addMethod(MyNewClass, #selector(method_returning_int:),
(IMP)..., "i#:i");
objc_registerClassPair(MyNewClass);
}
I'd like to be able to eliminate all those literal "v#:i" and so on. After all, those are supposed to be just the encodings of the method signatures as listed in the NSObject (MyNewClass) category. So I feel like I ought to be able to write something like
class_addMethod(MyNewClass_meta, #selector(class_method_taking_int:),
(IMP)..., #encode(__typeof__(+[NSObject class_method_taking_int:])));
Of course the syntax above is fantasy, but shouldn't there be something like this in Objective-C? And then I could hide the whole thing behind a simple macro and the code would be just beautiful.
Notice that I cannot use methodSignatureForSelector, because that assumes that I have an object that responds to the given selector, which I don't, because I haven't registered my class yet.
Also notice that the format of the string expected by class_addMethod isn't the same as the format of the string returned by #encode(foo), and in fact #encode(foo) can't encode function types at all — it just gives back "?" or "^?". So I guess I can't literally use #encode.
But is there anything I can do?

Call objective c++ method from objective c

I'm just learning Objective C (and objective-c++ for that matter) and I have an Objective-C++ class with the following constructor.
void InputManager::_init (int inputAreaX, int inputAreaY, int inputAreaWidth, int inputAreaHeight)
How do I invoke this from objective C?
This appears to be a pure C++ method so it would work exactly the same as in ordinary C++ (even in an Objective-C++ file). For instance you might have defined a variable on the stack:
InputManager mgr; // or, include constructor arguments if the class can't be default-constructed
mgr._init(x, y, w, h); // this assumes 4 variables exist with these names; use whatever parameter values you want
The name _init is a bit weird though; do you mean for this to be a constructor for the class? If so, InputManager::InputManager(int x, int y, int w, int h) should probably be defined instead.
If you actually want this class to be Objective-C only, the syntax and behavior are different.
You have two options:
Option 1.
Translate it into Objective-C only code. I'm not so good with C++, but this might be what it looks like in the .h:
-(id)initWithAreaX: (int) inputAreaX AreaY: (int) inputAreaY AreaWidth: (int) inputAreaWidth AreaHeight: (int) inputAreaHeight;
Since it looks like that's a constructor method, it would probably look like this in the implementation:
-(id)initWithAreaX: (int) inputAreaX AreaY: (int) inputAreaY AreaWidth: (int) inputAreaWidth AreaHeight: (int) inputAreaHeight {
self = [super init];
if(self) {
//Custom Initialization Code Here
_inputAreaX = inputAreaX;
_inputAreaY = inputAreaY;
_inputAreaWidth = inputAreaWidth;
_inputAreaHeight = inputAreaHeight;
}
return self;
}
And you might call it like this:
InputManager *object = [[InputManager alloc] initWithAreaX: 20 AreaY: 20 AreaWidth: 25 AreaHeight: 25];
Option 2.
The whole purpose of Objective-C++ is to allow the developer to integrate C++ and Objective-C code. You want to know how to call an Objective-C++ method from Objective-C, but the entire purpose of Objective-C++ is to integrate the two, so there's no point to trying to find a loophole to call an Objective-C++ method in a file that is otherwise completely Objective-C. So the second option is to just make the file that you want to call the Objective-C++ method in an Objective-C++ file with a ".mm" extension.
Hope this helps!

Retrieving data from singleton in a more clever way ?

I have some game data in my GameStateSingleton, which I don't want to retrieve every time explicitly with [[GameStateSingleton sharedMySingleton]getVariable], so I asked myself whether it is possible to do something like that :
In the interface file of my class, GameLayer I set up properties and variables like sharedHealth.
#interface GameLayer : CCLayer
{
int sharedHealth;
}
#property (nonatomic,assign) int sharedHealth;
and of course synthesize it in the implementation.
#synthesize sharedHealth;
In the initialization of GameLayer I would like to do something like :
sharedHealth = [self getCurrentHealth];
and add the corresponding method
-(int)getCurrentHealth{
int myHealth = [[GameStateSingleton sharedMySingleton]getSharedHealth];
return myHealth;
}
Is that possible ? From what I have experienced, I just seem to get crashes. How would I achieve my goal, to not always have to call the long method, as it always retrieves the same variable? There has to be a solution for this ...
You don't need an instance variable for that. You could just write a shortcut function like this:
- (int)sharedHealth {
return [[GameStateSingleton sharedMySingleton] getSharedHealth];
}
And where ever you need that value, you call [self sharedHealth].
You could also use a preprocessor macro instead. Just define this:
#define SharedHealth [[GameStateSingleton sharedMySingleton] getSharedHealth]
And then simply use that when you need the value.
Note, that in Objective-C you don't call getter methods "getVariable", but simply "variable". Mostly this is a convention, but if you start using KVC or KVO it's a rule you have to follow. So it's better to get used to it as soon as possible.
If it's just the repetitive typing that you're trying to avoid, you could use the old C way...
#define GAME_STATE [GameStateSingleton sharedMySingleton]
...and then...
int localValue = [GAME_STATE property];

What you can't do in C that you can do in Objective-C?

What you can't do in C (C99 standard) that you can do in Objective-C? (with code example if you please)
I'm going to be a little bit presumptuous and disagree with everyone else. While it's technically true that anything possible in one language is possible in another (where "possible" means "computable"), they differ in what you can express naturally and easily. The computer might be doing the same thing in response to the code you write in C, but you are writing radically different code to make it do those things.
As others have said, Objective-C provides a full runtime library written in C that will allow you to create Objective-C data structures and call C functions, but the code to do it will be very verbose, fairly roundabout and completely imperative. In Objective-C, the code is more declarative, more concise and far more readable.
In general, trying to write Objective-C things in C will only make your code worse than it would be using either language idiomatically. For example, here is a simple program written in Objective-C:
#interface NumberAdder : NSObject {
int storedValue;
}
- (id)initWithStoredValue:(int)value;
- (int)resultOfAddingStoredValue:(int)numberToAdd;
#end
#implementation NumberAdder
- (int)resultOfAddingStoredValue:(int)numberToAdd {
return numberToAdd + storedValue;
}
- (id)initWithStoredValue:(int)value {
if (!(self = [super init])) return nil;
storedValue = value;
return self;
}
#end
int main() {
id adder = [[NumberAdder alloc] initWithStoredValue:4];
int result = [adder resultOfAddingStoredValue:3];
printf("It is %d\n", result);
return 0;
}
And here is the same thing written in C with the Objective-C runtime (not tested, but should be roughly correct):
int returnPlusStoredValueImp(id self, SEL _cmd, int arg) {
int *storedValue = nil;
object_getInstanceVariable(self, "storedValue", &storedValue)
return arg + *storedValue;
}
id numberAdderInit(id self, SEL _cmd, int valueToStore) {
objc_super superInfo = {self, objc_lookupClass("NSObject")};
self = objc_msgSendSuper(super_info, sel_getName("init"));
if (!self) return nil;
object_setInstanceVariable(self, "storedValue", &valueToStore);
return self;
}
void createNumberAdderClass() __attribute(constructor)__ {
Class NumberAdder = objc_allocateClassPair(objc_lookupClass("NSObject"), "NumberAdder", 0);
if (!NumberAdder) return;
class_addIvar(NumberAdder, "storedValue", sizeof(int), 4, "i"); // I'm actually not sure if the fourth argument is correct, so it's probably wrong, but just take that as a sign of how much this way of coding sucks
objc_registerClassPair(NumberAdder);
SEL nameOfPlusStoredValue = sel_registerName("resultOfAddingStoredValue:");
SEL nameOfInit = sel_registerName("initWithStoredValue:");
class_addMethod(NumberAdder, nameOfPlusStoredValue, returnPlusStoredValueImp, "i#:i");
class_addMethod(NumberAdder, nameOfInit, numberAdderInit, "##:i");
}
int main() {
id adder = objc_msgSend(objc_lookupClass("NumberAdder"), sel_getName"alloc");
adder = objc_msgSend(adder, sel_getName("initWithStoredValue:"), 4);
int result = (int)objc_msgSend(adder, sel_getName("resultOfAddingStoredValue:"), 3);
printf("It is %d\n", result);
return 0;
}
Absolutely nothing. Objective-C's OO features are implemented as a small runtime library written in C.
While some commenters might point out that Objective-C has blocks and C doesn't, that's actually a GCC/LLVM extension to C that Objective-C makes use of, it's not an ObjC feature.
As Graham said -- there is absolutely nothing that can be done in Objective-C that can't be done in C. Of course, there isn't anything you can do in C, either, that can't be done in assembly. It is just a matter of typing.
(I was hoping that the the assembly mention would be enough to indicate that, no, I'm not remotely suggesting that writing OO patterns in pure C is remotely a productive thing to do...)
There are a few additional points of interest:
Objective-C started out as a preprocessor that turned Objective-C code into C code that could be compiled by a standard C compiler. That is, Objective-C was originally never directly compiled, but translated to straight C, then compiled.
Objective-C objects can be thought of as C structures where the first entry in the structure -- the isa -- is always a pointer to the metadata -- the Class -- that describes the structure/instance.
Blocks are an extension to C, now proposed as an addition to the C language in WG-14 (C standards committee). Blocks, as implemented by Apple, absolutely do not require an executable stack. It was a hard requirement in their design.
LLVM has a rewriter that can actually rewrite Objective-C to C and has, apparently, been used to enable Objective-C coding in Xbox 360 games (see http://permalink.gmane.org/gmane.comp.compilers.llvm.devel/31996).
There isn't such a thing. Generally, you can program anything in any programming language.