Calling Objective-C method from C code - objective-c

I'm trying to call a method implemented in Obj-C from C code as follows:
// MainViewController.m
- (void)Test
{
[self outputLine:#"Called from MyCode.c"];
}
.
.
.
cFunc(id param);
.
.
.
// MyCode.c
void cFunc(id param)
{
[param Test]; // compilation error: Parse issue: Expected expression
}
I guess it happens since the MainViewController is not declared in MyCode.c, but when I #include the MainViewController.h I get tons of other errors that suggests I'm totally wrong...
How should I handle it correctly?
TIA

You should compile the MyCode.c file as Objective-C. Objective-C is a superset of C, but it's not true the other way around. You can't have Objective-C code interspersed with your "pure C" code if you are intending to compile it as C.

Check: using objc_msgSend to call a Objective C function with named arguments
void cFunc(id param) {
objc_msgSend(param, sel_getUid("Test"));
}
But, as per the link above, this is dangerous for a few reasons, if your arguments don't fit in registers (i.e. floats, structs, blah blah).
The accepted way of doing this is to cast objc_msgSend:
void cFunc(id param) {
// Now let's pretend that you want to send someFloat to your method
void (*objc_msgSendTyped)(id self, SEL _cmd, float bar) = (void*)objc_msgSend;
float someFloat = 42.f;
objc_msgSendTyped(param, sel_getUid("Test"), someFloat);
}

Just change your myCode.c to myCode.m :P
Don't be afraid to put C code in an Objective-C file.

Related

Is there any way I can tell from what class/method a method is called?

I have a preprocessor macro that I use like this:
#implementation MyClass
- (void)methodA
{
MyLog("Hello, method A!");
}
- (void)methodB
{
MyLog("Hello, method %#!", #"B");
}
#end
And after macro expansion it looks like:
#implementation MyClass
- (void)methodA
{
; NSLog([NSString stringWithFormat:#"%s - %#", __func__, "Hello, method A!"]); ;
}
- (void)methodB
{
; NSLog([NSString stringWithFormat:#"%s - %#", __func__, "Hello, method %#!"], #"B"); ;
}
#end
This will result in these being printed for their respective methods:
-[MyClass methodA] - Hello, method A!
-[MyClass methodB] - Hello, method B!
I want to change this to a set of Objective-C or Swift methods, which I can call the same way and would give me the same result. I don't want to manage an object, so these should be class/static methods. Is it possible to tell that I'm in a particular class/method and only use a particular log prefix while in there?
If not, is there any other way to use methods to mimic the behavior I achieved with the macros?
Generally the Swift tool you want here is #function. For example:
func MyLog(msg: String, function: StaticString = #function) {
print("\(function) - \(msg)")
}
#function, when used as a default parameter value, evaluates to the function that at the calling site. Since it's a default value, you don't have to pass a function parameter.
This is not compatible with ObjC, however. For that, you'll still need macros. If you want to forward along an ObjC macro to Swift, you'd do something like:
#define MYLog(message) [Log log:message function:#(__FUNCTION__)]
You'd then need to write MyLog this way:
struct Log {
static func log(msg: String, function: String = #function) {
// ...
}
}
It has to be in a struct to be accessible to ObjC (or it could be an enum), and you have to make function of type String rather than StaticString because ObjC can't generate StaticString.
Build like this, in Swift, you would call:
Log.log("my message")
and in ObjC you would call
MyLog("my message")
I produce (by macro expansion) a similar result.
In GERuntimeConstants.h, i define
extern void QuietLog(NSString *format, ...);
in GERuntimeConstants.m, i provide QuietLog as :
void QuietLog(NSString *format, ...) {
if (format == nil) {
printf("nil\n");
return;
}
// Get a reference to the arguments that follow the format parameter
va_list argList;
va_start(argList, format);
// Perform format string argument substitution, reinstate %% escapes, then print
NSString *s = [[NSString alloc] initWithFormat:format arguments:argList];
printf("%s\n", [[s stringByReplacingOccurrencesOfString:#"%%" withString:#"%%%%"] UTF8String]);
va_end(argList);
}
in GEMacros, i define
#define __MPLOGWITHFUNCTION(s, ...) \
QuietLog(#"%s : %#",__FUNCTION__,[NSString stringWithFormat:(s), ##__VA_ARGS__])
#define MPLOG(...) __MPLOGWITHFUNCTION(__VA_ARGS__)
I include GEMacros.h in my .pch
anywhere i want to log , i would have a single line of code that looks like the following example :
- (void)cleanupWithError:(NSString *)status message:(NSString *)message {
MPLOG(#"*** Cleaning up , status[%#], message[%#]",status,message);
and this statement translates to this in the console :
-[EHRCall cleanupWithError:message:] : *** Cleaning up , status[INVALID_PARAMETERS], message[No api user with api key [patient01ApiKey]]
So in my code, i use MPLOG as NSLog (always). The definition via _MPLOGWITHFUNCTION is because I have other macros that are tuned to the build. This definition is for logging while working a debug build. For distro MPLOG defines down to ;.

Swift 2.0 interop with Objective C not working as expected?

I'm porting a Swift 1.2 framework to 2.0. After fixing the 3 million compiler errors courtesy of the new Swift 2.0 error handling scheme, I was finally able to link my test app (written in Objective C) to use the updated framework.
Xcode version 7.0 beta 3 (7A121l)
However, I ran into a problem. Some Swift functions are no longer generated into the automatically generated Objective C header (MyFramework-Swift.h) used by the Objective C test app.
Here is an example of a function that is not exposed: (My actual framework function returned an enum, but I tried to simplify to illustrate the problem more clearly).
public func calculateImportantValueDangerously() throws -> Int
{
return 42
}
Note that other functions like the following actually do get exposed as expected (and can be called):
public func doSomething()
{
}
public func doSomethingDangerous() throws
{
}
public func calculateMeaninglessValue() -> Int
{
return -1
}
Here's the Objective C side:
MyClass *newInstance = [[MyClass alloc] init];
[newInstance doSomething];
NSError *error = nil;
[newInstance doSomethingDangerousAndReturnError:&error];
long meaninglessValue = [newInstance calculateMeaninglessValue];
NSLog(#"%ld", meaninglessValue);
long importantValue = [newInstance calculateImportantValueDangerouslyAndReturnError:&error]; <-COMPILE ERROR
NSLog(#"%ld", importantValue);
From watching this video, I had expected that it should "just work":
https://developer.apple.com/videos/wwdc/2015/?id=401
...but it seems like we can't currently use functions that both throw and return a value.
Is this a bug, or not implemented feature? My apologies if I missed something in the release notes somewhere.
Any advice appreciated.
It is not possible.
If you annotate your method with #objc you will see the problem.
Throwing method cannot be marked #objc because it returns a value of
type 'Int'; return 'Void' or a type that bridges to an Objective-C
class
You can return only objects, primitives are not supported.
Although the selected answer is correct; you can't return an Int for a throwing function, I wanted to note an alternate solution since Apple has this same issue for a function in the CoreData framework:
func countForFetchRequest(request: NSFetchRequest, error: NSErrorPointer) -> Int
Note that in this case Apple is not using the throws pattern and instead reverting to the classic NSError out parameter mechanism.

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!

What is the best way output the name of the class who's method is being called?

I am aware of NSStringFromClass.
My question relates to the situation where the same method is implemented in multiple classes in an inheritance tree, and you want to debugging information as to which class it is executing from.
Example:
Let us have three classes: A-->B-->C , inheriting as displayed by the arrows.
If each of them has a method foo(), defined:
-(void) foo
{
// Do some work particular to the class it is in.
.....
//Each method ends with the debugging statement:
NSLog("In foo of class:%$",NSClassFromString([self class]));
}
The problem occurs when foo of Class B, calls [super foo]. When [super foo] (i.e. Class A) reaches the NSLog statement, [self class] returns class B, and not A.
Likewise if C called [super foo], the log statement in super would log class C.
What I want to do, is output the class whose method implementation is being executed - so if class B calls [super foo], then the log statement in [A foo] outputs Class A.
The simple way is to replace NSClassFromString with a hardcoded string representing the class name, but I was wondering if there is a better way to do this ?
You can use __PRETTY_FUNCTION__ to include both the class and the method name:
NSLog(#"Greetings from %s", __PRETTY_FUNCTION__);
I don't believe that there is a compiler-time macro for just the class name.
There might not be a macro for class, but there is __FILE__ and __LINE__ macros in the C language. They expand to the current file and line number. You can use them in NSLog. I use __PRETTY_FUNCTION__ when I remember it, but I remember __FILE__ and __LINE__ more.
Example:
NSLog( #"%s %d", __FILE__, __LINE__ );
Remember that __FILE__ isn’t an Objective-C string.
The problem occurs when foo of Class B, calls [super foo]. When [super
foo] (i.e. Class A) reaches the NSLog statement, [self class] returns
class B, and not A.
Sure. That's because self points to an object, and that object's class doesn't change just because you call a method of the superclass.
The simple way is to replace NSClassFromString with a hardcoded string
representing the class name, but I was wondering if there is a better
way to do this?
As others have pointed out, you can use a macro like __PRETTY_FUNCTION__, but I think the simple and obvious approach is the best. You know the name of the class when you're writing the code, so you can write:
NSLog("In foo of class: %#", #"ClassA");
Each of your classes has its own implementation of your method, so each one can print its own class name in the message. Something like __PRETTY_FUNCTION__ is useful when you're writing a debug macro that you're going to use in multiple functions. That's not the case here. Using the obvious approach makes it that much easier to see what's going on, and that's important during debugging (which I assume is what you're trying to do here).
i think you would have to walk up the class hierarchy using class_getSuperclass and class_getInstanceMethod, comparing differences in the methods. do that to determine the objc class, then use class_getName or NSStringFromClass to get its name.
This would look something like:
NSString* MONClassNameWhichImplementsMethod(id Self, SEL cmd);
and
- (void)method
{
NSLog(#"%# - %#",
MONGetClassWhichImplementsMethod(self, _cmd),
NSStringFromSelector(_cmd)
);
}
and
// NOT COMPILED -- FOR ILLUSTRATION ONLY
Class MONClassWhichImplementsMethod(Class cls, SEL cmd) {
assert(cls && cmd && "srsly?");
Class super = class_getSuperclass(cls);
Method m1 = class_getInstanceMethod(cls, cmd);
assert(m1 && "srsly?");
Method m2 = class_getInstanceMethod(super, cmd);
if (0 == m2) {
return cls;
}
else if (m1 != m2) {
return cls;
}
else {
return MONClassWhichImplementsMethod(super, cmd);
}
}
NSString* MONClassNameWhichImplementsMethod(id Self, SEL cmd) {
return NSStringFromClass(MONClassNameWhichImplementsMethod(Self.class, cmd));
}
if it blows up from deep recursion, you've another problem.

Using iterateFunc to call objective c method

Using spacemanager, I need to perform an action on select bodies after each step, so I figured that defining my own C function for iterateFunc would be the way to go.
Everything works great, except I'm not sure how to then call an obj c method in the same class. In other words, an obj c class contains both the c function replacing iterateFunc, and the method that needs to be called. I don't see how to tell the c function what 'self' is, such that I can call the method. As far as i can tell, there's no way to pass in any extra info to the new iterateFunc.
Any ideas, or a better way to go about things?
Update:
Thanks for the response. Declaring a new spacemanager, one can redefine its iterateFunc:
smgr = [[SpaceManager alloc] init];
smgr.iterateFunc=doThisFunc;
In the same class, a "doThisFunc" function can be declared.
In spacemanager, this iterateFunc is called from the "step" method:
-(void) step: (cpFloat) delta
{
.....
cpSpaceHashEach(_space->activeShapes, _iterateFunc, self);
....
}
So my first thought was to subclass spacemanager, and in my custom step method, call cpSpaceHashEach with my own class, instead of self (the spacemanager, that is). Halfway there, I realized that I didn't even have to do that, as subclassing and defining my own step method was all I needed to do. My new step method:
-(void) step: (cpFloat) delta
{
[super step:delta];
//Having of course set the "myObject" variable elsewhere as my other object
[myObject doThis];
}
Thanks, bbum for both your answers, and for helping me craft better questions in the future.
Holy vagueness, batman, where's the code snippet? Thankfully, the Magic Powers of Google save the day.
To answer this question requires a few bits of detail:
What is the declaration of iterateFunc?
Oh. It is a cpSpaceHashIterator. Not helpful.
Ah... there it is:
typedef void (*cpSpaceHashIterator)(void *obj, void *data);
It looks like the void *data argument is your answer. Specifically, it looks like that is passed through transparently to your iterator function. That is, if you call:
cpSpaceEachBody(cpSpace *space, cpSpaceBodyIterator func, void *data)
Like this:
cpSpaceEachBody(space, funcPtr, (void *)self);
Then your iterator func could do this:
void iteratorFunc(void *obj, void *data) {
[(MyClass *)data iterateThis: obj];
}