call objective-c method from extern "C" - ios

I have one temp.mm class which contains implementation for test class & extern "C" class. I am trying to call objective-c method in extern "c" class(i.e. testMethod & testMethod1).
How can i call objective-c method in extern "C" class function?.
I am new to Objective-c
I mention the example code below..
import<test.h>
#implement test
-(void)testMethod
{
//code
}
-(NSString*)testMethod1:(NSString *)value
{
//code
return value;
}
void callMethod()
{
how to call testMethod & testMethod1 in this also?
}
#end
extern "C"
{
how to call testMethod & testMethod1?
}

The C code part is (and must be) outside your class' implementation, so you'll have to create an object of test and then call it's methods, like follows:
void callMethod()
{
test *test = [[test alloc] init];
[test testMethod];
const char *yourCString = "yourCString";
[test testMethod1:[NSString stringWithCString:yourCString encoding:NSUTF8StringEncoding]];
}
You don't need the extern "C" part in the implementation (.m or .mm files), this is just needed in the header (.h files) when you want to mark them as "plain old c code" (not C++).
See: Is it required to add 'extern C' in source file also?

too call the method at initial .....
use:
[self testmethod];
[self testmethod1];
if you like to inherit this method in to another class just import the .m file.

Related

Where is the specific implementation used in objective-c?

Hello everyone i am new to objective c. The following code is not mine. I am just trying to understand how it works. I have a ViewController that has this property in the .h file.
#property (nullable, nonatomic, copy) dispatch_block_t logHandler;
Inside the .m file the logHandler is called when a button is pressed with the following code.
- (IBAction)login:(id)sender {
if (nil != self.logHandler) {
self.logHandler();
}
}
Then the logHandler is called which exists in another class NSObject file
inside the .h file
#interface LogFlow : NSObject<TheFlowController>
#end
and in .m file
- (UIViewController *)rootViewController {
LogViewController *viewController = LogViewController.newInstance;
viewController.logHandler = ^{
UIViewController *logController = [self startNewLogFlow];
[self.navigationController pushViewController:logController animated:YES];
};
return viewController;
}
I do not understand why the logHandler exists in another class and why it is called from this specific class, and how is it possible to call this code from another class without any import used? I am trying to understand when to use this kind of implementation and how to use it. Any help appreciated.
The construct that you see in the rootViewController:
^{
UIViewController *logController = [self startNewLogFlow];
[self.navigationController pushViewController:logController animated:YES];
};
This is what's known as a "Block" in Objective-C. You may find other references to it in other languages as an "anonymous function" or a "closure". Those names apply here as well.
This creates an object that is just a function, but the function doesn't have a name. You can also assign the unnamed function to variables and call it from the variable - which is what happens here. The anonymous function, the block, is assigned to the logHandler instance variable of the viewController object. Later some other code can call that function through the variable as you see in your login: example.
Here's a simpler block that is just plain Objective-C:
int squareFunction(int x) {
return x * x;
}
void playWithSquares(void);
void playWithSquares(void) {
int nine = squareFunction(3);
int alsoNine = (^(int x){
return x * x;
})(3);
}
The declaration of squareFunction creates a named function that calculates the square of two integers.
You also see the the expression:
^(int x){
return x * x;
};
This also creates a function that calculates the square of an integer, but it doesn't bind that function to a name. Since it has no name we call the function immediately by wrapping it in parenthesis and then passing it arguments (<anonymous function expression>)(3)
We could store the anonymous function in a variable:
typedef int (^SquaresBlock)(int);
SquaresBlock myBlock = ^(int x){
return x * x;
};
and then call it later using squaresBlock(3)
Blocks are very important in Cocoa's use of Objective-C so you should learn more about them.
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html

(Reflection) Calling A Method With Parameters By Function Name In Swift

Context
I have an instance of class called Solution and I have a function name as a string functionName that I want to call on the Solution instance solutionInstance. I have the parameters for the function in an array and I'd like to pass those as well.
I am using the Swift compiler to compile all of my .swift files together (swiftc with a files enumerated and then -o and the output file name) then I run the final output.
Python Example
Here is how I do this in Python:
method = getattr(solutionInstance, functionName) # get method off of instance for function
programOutput = method(*testInputsParsed) # pass the list of parameters & call the method
Purpose
This is server-side code that runs in a container to run a user's code. This code lives in a "Driver" main.swift file that calls the methods and orchestrates testing.
Problem
Swift is statically typed and I've been searching around and most sources say there is limited reflection support in Swift (and suggest to "reach into Objective-C" to get the functionality desired).
Swift is not my native language (TypeScript/JavaScript, Java, Python strongest, then C# and C++ mild, then just implementing Swift code for this feature now) so I'm not sure what that means and I haven't been able to find a definitive answer.
Question
How can I call a function by its name on a Solution class instance (it implements no protocols, at least by me) and pass an array of parameters in Swift (using reflection)? How does my setup need to change to make this happen (importing libraries, etc.)
Thank you!
Referenced Posts
Calling Method using reflection
Does Swift support reflection?
Call a method from a String in Swift
How to invoke a class method using performSelector() on AnyClass in Swift?
Dynamically call a function in Swift
First of all, as you noted Swift doesn't have full reflection capabilities and rely on the coexisting ObjC to provide these features.
So even if you can write pure Swift code, you will need Solution to be a subclass of NSObject (or implement NSObjectProtocol).
Playground sample:
class Solution: NSObject {
#objc func functionName(greeting: String, name: String) {
print(greeting, name)
}
}
let solutionInstance = Solution() as NSObject
let selector = #selector(Solution.functionName)
if solutionInstance.responds(to: selector) {
solutionInstance.perform(selector, with: "Hello", with: "solution")
}
There are other points of concern here:
Swift's perform is limited to 2 parameters
you need to have the exact signature of the method (#selector here)
If you can stick an array in the first parameters, and alway have the same signature then you're done.
But if you really need to go further you have no choice than to go with ObjC, which doesn't work in Playground.
You could create a Driver.m file of the like:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
id call (NSObject *callOn, NSString *callMethod, NSArray <NSObject *>*callParameters)
{
void *result = NULL;
unsigned int index, count;
Method *methods = class_copyMethodList(callOn.class, &count);
for (index = 0; index < count; ++index)
{
Method method = methods[index];
struct objc_method_description *description = method_getDescription(method);
NSString *name = [NSString stringWithUTF8String:sel_getName(description->name)];
if ([name isEqualToString:callMethod])
{
NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:description->types];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
NSObject *parameters[callParameters.count];
for (int p = 0; p < callParameters.count; ++p) {
parameters[p] = [callParameters objectAtIndex:p];
[invocation setArgument:&parameters[p] atIndex:p + 2]; // 0 is self 1 is SEL
}
[invocation setTarget:callOn];
[invocation setSelector:description->name];
[invocation invoke];
[invocation getReturnValue:&result];
break;
}
}
free(methods);
return (__bridge id)result;
}
Add it to a bridging-header (for Swift to know about what is in ObjC):
// YourProjectName-Bridging-Header.h
id call (NSObject *callOn, NSString *callMethod, NSArray *callParameters);
And call it with a Solution.swift like this:
import Foundation
class Solution: NSObject {
override init() {
super.init()
// this should go in Driver.swift
let result = call(self, "functionNameWithGreeting:name:", ["Hello", "solution"])
print(result as Any)
}
#objc
func functionName(greeting: String, name: String) -> String {
print(greeting, name)
return "return"
}
}
output:
Hello solution
Optional(return)
Edit: compilation
To compile both ObjC and Swift on the command line you can first compile ObjC to an object file:
$ cc -O -c YouObjCFile.m
Then compile your Swift project with the bridging header and the object file:
$ swiftc -import-objc-header ../Your-Bridging-Header.h YouObjCFile.o AllYourSwiftFiles.swift -o program
working sample

Use of undeclared identifier error in my case

My code invokes a C library function:
#implementation Store
...
-(void) doWork {
// this is a C function from a library
int data = getData();
...
}
end
I am unit testing the above function, I want to mock the C function getData() in my test, here is my test case:
#interface StoreTests : XCTestCase {
int mData;
Store *store;
}
#end
#implementation StoreTests
-(void) setUp {
[super setUp];
mData = 0;
store = [[Store alloc] init];
}
-(void) testDoWork {
// this call will use the mocked getData(), no problem here.
[store doWork];
}
// mocked getData()
int getData() {
mData = 10; // Use of undeclared identifier 'mData', why?
return mData;
}
...
#end
Why I get complier error:
Use of undeclared identifier 'mData' inside mocked getData() function?
You are misunderstanding how instance methods and variables work.
Every instance method has a variable self which references the current instance (or "current object") and a use of an instance variable, such as mData, is shorthand for accessing that variable using self, e.g self->mData, where -> is the (Objective-)C operator for field access. So your setup method written "long hand" is:
-(void) setUp {
[super setUp];
self->mData = 0;
self->store = [[Store alloc] init];
}
But where does self, the reference to the instance, itself come from? Well it's not magical, just hidden, it is passed to an instance method automatically as a hidden extra argument. At this point which switch to pseudo-code to show this. Your setup method is effectively compiled as:
-(void) setUp withSelf:(StoreTest *)self {
[super setUp];
self->mData = 0;
self->store = [[Store alloc] init];
}
and a call such as:
StoreTests *myStoreTests = ...
[myStoreTests setup];
is effectively compiled as something like:
[myStoreTests setup withSelf:myStoreTests];
automatically adding the extra self argument.
Now all the above only applies to methods, and enables them to access instance variables and methods, it does not apply to plain C functions - they have no hidden self argument and cannot access instance variables.
The solution you mention in the answer you added of declaring mData outside of the interface:
int mData;
#interface StoreTests : XCTestCase {
Store *store;
}
#end
changes mData into a global variable, instead of being an instance variable. C functions can access global variables. However this does mean that every instance of the class shares the same mData, there is only one mData in this case rather than one for every instance.
Making an instance variable into a global is therefore not a general solution to to issues like this, however as it is unlikely that you will have more than one instance of your StoreTests class it is a suitable solution in this case.
You should however make one change: you can only have one global variable with a given name with a program, so your mData must be unique and is accessible by any code within your program, not just the code of StoreTests. You can mitigate this my declaring the variable as static:
static int mData;
this keeps the variable as global but only makes it visible to code within the same file as the declaration, which is probably just the code of StoreTests.
HTH
I found one solution for my question, that is declare mData above #interface StoreTests : XCTestCase, something like this:
int mData;
#interface StoreTests : XCTestCase {
Store *store;
}
#end
...

How to communicate from pure C (.c files) SDK to IOS (obj-C, .m files) framework?

Preface: I have little experience with C integration in iOS, feel free to correct me on any misinterpretations I have about this.
I have a project that has a custom 2-tier "SDK" both written in C. The coreSDK makes method calls to the deviceSDK which communicates with the ios framework to execute hardware actions (ie. enable camera) or retrieve device information (ie. path to NSDocumentDirectory).
Unfortunately, due to the infrastructure, both SDK file extensions use (.h) and (.c) and cannot be changed to (.m) as some sources recommended. According to what I've read, I can create C-callbacks to the ObjC methods but that's only really viable for singletons, and the C-callback needs to be within the scope of the (.m) file.
I have tried creating a wrapper class in ObjC such that it has a C-callback from which the deviceSDK calls to, but when including the header(.h) for that (.m), the compiler seems to crash. If my understanding is correct, it's because the C-compiler cannot interpret the ObjC language contained in the (.m).
I believe theoretically is possible to write iOS apps in pure C with ObjC runtime, but ideally would rather not go down that route as what I've seen is absurdly complicated.
An example workflow
ViewController.m method calls to coreSDK method (.c)
coreSDK method calls to deviceSDK method (.c)
deviceSDK needs to retrieve (for example) NSDocumentDirectory (or enable camera)
How can I achieve this?
Code examples would be most comprehensive and appreciated.
Thanks!
These are some(not all) references I've already looked into...
How to write ios app purely in c
Pure C function calling Objective-C method
C function calling objective C functions
Using native objective-c method for C callbacks
Callback methods from C to Objective-C
Mixing C functions in an Objective-C class
How to call an Objective-C method from a C method
How to use pure C files in an objective-C project
Edit: 2016-07-21
To clarify the issue, I'm having trouble making calls from C methods in (.c) files to ObjC methods in (.m) files, or figuring out an alternative means to retrieve information such as (for example) NSDocumentsDirectory in ObjC (.m files) and passing back to C in (.c) files.
Example Code: Of course it's incorrect but it's along the lines of my expectations or what I'm hoping to achieve.
//GPS.h
#include "GPSWrapper.h"
STATUS_Code GPSInitialize(void);
//GPS.c
#include "GPS.h"
STATUS_Code GPSInitialize(void) {
GPS_cCallback();
}
//GPSWrapper.h
#import <Foundation/Foundation.h>
#interface GPSWrapper: NSObject
- (void) testObjC;
#end
//GPSWrapper.m
#import "GPSWrapper.h"
static id refToSelf = nil;
#implementation GPSWrapper
- (void) testObjC {
// just an example of a ObjC method call
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(documentsDirectory);
}
#end
static void GPS_cCallback() {
[refToSelf testObjC];
}
This line #include "GPSWrapper.h" in your example is the problem. You can't include a header that has ObjC syntax in a file that's being compiled as C. Any interface to the ObjC side that's being included in your C code needs to be broken out into its own header that contains only valid C. Here's a demo of what you need:
First, header and implementation file for the C-only stuff.
// CUtils.h
// OCFromC
#ifndef CUtils_h
#define CUtils_h
#include <stdio.h>
void doThatThingYouDo();
void doThatThingWithThisObject(const void * objRef);
#endif /* CUtils_h */
// CUtils.c
// OCFromC
// Proof that this is being compiled without ObjC
#ifdef __OBJC__
#error "Compile this as C, please."
#endif
#include "CUtils.h"
#include "StringCounterCInterface.h"
void doThatThingYouDo()
{
printf("%zu\n", numBytesInUTF32("Calliope"));
}
void doThatThingWithThisObject(const void * objRef)
{
size_t len = numBytesInUTF32WithRef(objRef, "Calliope");
printf("%zu\n", len);
}
Note that second function; if you need to, you can pass around an object reference in C land, as long as it's cloaked in a void *. There's also some casting that needs to be done for memory management. More on that below.
This is the exciting ObjC class we'll be using:
// StringCounter.h
// OCFromC
#import <Foundation/Foundation.h>
#interface StringCounter : NSObject
- (size_t)lengthOfBytesInUTF32:(const char *)s;
#end
// StringCounter.m
// OCFromC
#import "StringCounter.h"
#implementation StringCounter
- (size_t)lengthOfBytesInUTF32:(const char *)s
{
NSString * string = [NSString stringWithUTF8String:s];
return [string lengthOfBytesUsingEncoding:NSUTF32StringEncoding];
}
#end
Now, this is the important part. This is a header file that declares C functions. The header itself contains no ObjC, so it can be included in CUtils.c as you saw above.
// StringCounterCInterface.h
// OCFromC
#ifndef StringCounterCInterface_h
#define StringCounterCInterface_h
// Get size_t definition
#import <stddef.h>
size_t numBytesInUTF32(const char * s);
size_t numBytesInUTF32WithRef(const void * scRef, const char *s);
#endif /* StringCounterCInterface_h */
This is the connection point. Its implementation file is compiled as ObjC, and it contains the definitions of those functions just declared. This file imports the interface of StringCounter, and so the functions can use methods from that class:
// StringCounterCInterface.m
// OCFromC
#ifndef __OBJC__
#error "Must compile as ObjC"
#endif
#import "StringCounterCInterface.h"
#import "StringCounter.h"
size_t numBytesInUTF32(const char * s)
{
StringCounter * sc = [StringCounter new];
// Or, use some "default" object in static storage here
return [sc lengthOfBytesInUTF32:s];
}
size_t numBytesInUTF32WithRef(const void * objRef, const char * s)
{
StringCounter * sc = (__bridge_transfer StringCounter *)objRef;
return [sc lengthOfBytesInUTF32:s];
}
Now, in main or wherever you like you can exercise those functions from CUtils:
// main.m
// OCFromC
#import <Foundation/Foundation.h>
#import "StringCounter.h"
#import "CUtils.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
doThatThing();
// Create an object reference
StringCounter * sc = [StringCounter new];
// Tell ARC that I know this is dangerous, trust me,
// pass this reference along.
const void * scRef = (__bridge_retained void *)sc;
doThatThingWithThisObject(scRef);
}
return 0;
}
The bridging cast, along with its counterpart in StringCounterCInterface.m, lets you move an ObjC object through areas where ARC cannot go. It bumps the object's retain count before it is hidden in the void *, so that it will not be accidentally deallocated before you can __bridge_transfer it back to ObjC land.
One final note: If you are going to be passing object references around in C a lot, you might consider doing typedef void * StringCounterRef; and changing the signatures of everything appropriately.

Getters and setters for constants?

Is is possible to create getters and setters for constants? I want to refer to a constant directly, and have it instantiate itself if it's value is nil. A constant declared like this:
// Prefs.h
extern MyClass * const kThing;
// Prefs.m
MyClass * const kThing = nil;
and the getter/setter would look like:
// getter
+ (MyClass *)kThing
{
_kThing = _kThing ? : [MyClass new];
return _kThing;
}
// setter
+ (void)setKThing:(MyClass *)myClass
{
_kThing = myClass
}
And then I could use it like:
[kThing doSomething];
Is this possible?
edit edited the methods to class methods
What you describe are not constants, they are global variables. You cannot define getters and setters for them, but you can use their values to back class methods, which is precisely what you have done.
However, when you send message like this
[kThing doSomething];
the global variable is used directly, bypassing your getter. If you want to go through a getter, you can write
[[MyClass kThing] doSomething];
or inside methods of MyClass you can write
[[[self class] kThing] doSomething];
Another note is that when yo implement accessor methods like that, you should make the backing variables static, rather than extern. This will ensure that other modules cannot access these variables bypassing your getters.
Global variable declaration in other file is very dangerous in objective C. Ideally we use sharedInstance. Try like this:
In MyGame.h
#interface MyGame : NSObject
{
int mScore;
}
#property(nonatomic,assign) int score;
+(MyGame*)sharedObject;
-(void)someFunction;
#end
In MyGame.m
static MyGame *gGame = nil;
#implementation MyGame
#synthesize score = mScore;
+(MyGame*)sharedObject
{
if(!gGame)
{
gGame = [[MyGame alloc] init];
}
return gGame;
}
-(void)someFunction
{
}
#end
To access anywhere in project:
#import "MyGame.h"
[MyGame sharedObject].score;
[MyGame sharedObject] someFunction];
The short answer is that this is not possible.
MyClass * const kThing = nil;
means that kThing is a constant pointer, which means that the address in memory that it points to cannot be changed. So once it's set to nil, it can't later be set to a new object.

Resources