How do I pass (by value) a struct in Objective-C? - objective-c

This one has been driving me mad! I have a struct:
typedef struct{
int a;
}myStruct;
Then I have:
myStruct tempStruct;
I am trying to pass the struct to a class method whose implementation is:
- (void) myFunc:(struct myStruct)oneOfMyStructs{};
I call the method like so:
[myClass myFunc:(struct myStruct)tempStruct];
The compiler complains about "Conversion to non-scalar type requested." All I want to do is pass a struct into a class method, but the syntax has me a bit confused. I'm new to Objective-C. Please let me know if you can see where I'm going wrong. I've not been able to pass by reference either, so if you could help me out with that, that would be great!
Thanks!

Since you have typedef-ed it to myStruct, you don't need to (indeed mustn't) include the struct keyword in the function signature or the call:
typedef struct tag_myStruct
{
int a;
}
myStruct;
- (void) myFunc:(myStruct) x {}
[myClass myFunc:tmpStruct];
should be sufficient. (Compare all those Cocoa functions that take things like NSRects.)

Related

How to declare a method that takes a block as a callback

I have a method that I'd like to call like so:
void (^someblock)()=^{
NSLog(#"I want to know");
};
[Item getCacheAndCallback:self.menuItemID andCallback:someblock];
How would I declare this in my header file? I have tried
+(void)getCacheAndCallback:(int)menuItemID andCallback:(^());
but says "Expected a type". I thought this was supposed to go to void for type.
+(void)getCacheAndCallback:(int)menuItemID andCallback:(void(^)(void))completionBlock;
Putting block types directly into method signatures can get messy as you've found. I would suggest you use a typedef to make it cleaner:
typedef void(^VoidBlock)();
Now you can write your block declaration as:
VoidBlock someBlock = ^{ NSLog(#"I want to know"); };
and your method declaration as:
+ (void) getCacheAndCallback:(int)menuItemID andCallback:(VoidBlock)callBack;
Note: that typedef does not introduce a new type, just a shorthand. This means, for example, that you can declare a block using the full type (or even a different typedef with the same full type) and use it as VoidBlock.
Block syntax is weird. I keep this link handy to reference any time I happen to forget something: fuckingblocksyntax.com

Is there a way to reflectively call a function in Objective-C from a string?

Are there any Objective-C runtime functions that will allow me to get a function (or block) pointer from a string identifying the function? I need some way to dynamically find and invoke a function or static method based on some form of string identifying it.
Ideally this function should be able to exist in any dynamically loaded library.
Looking at Objective-C Runtime Reference, the best bet looks like class_getClassMethod, but there don't appear to be any function-related functions in this reference. Are there other raw C ways of getting a pointer to a function by name?
if you want to invoke some static objc method, you can make it as a class method of a class
#interface MyClas : NSObject
+ (int)doWork;
#end
and call the method by
[[MyClass class] performSelector:NSSelectorFromString(#"doWork")];
if you real want to work with C-style function pointer, you can check dlsym()
dlsym() returns the address of the code or data location specified by
the null-terminated character
string symbol. Which libraries and bundles are searched depends on the handle
parameter If dlsym() is called with the special handle RTLD_DEFAULT,
then all mach-o images in the process
(except those loaded with dlopen(xxx, RTLD_LOCAL)) are searched in the order they were loaded. This
can be a costly search and should be avoided.
so you can use it to find the function pointer base on asymbol name
not sure why you want to do this, sometimes use function table can do
typedef struct {
char *name,
void *fptr // function pointer
} FuncEntry;
FuncEntry table[] = {
{"method", method},
{"method2", method2},
}
// search the table and compare the name to locate function, you get the idea
If you know method signature you can create selector to it with NSSelectorFromString function, e.g.:
SEL selector = NSSelectorFromString(#"doWork");
[worker performSelector:selector];
You may be able to do what you want with libffi. But unless you are doing something like create your own scripting language or something like that where you need to do this sort of thing a lot. It is probable overkill
I've wondered the SAME thing.. and I guess, after having researched it a bit.. there is NOT a "standard C" way to do such a thing.. (gasp).. but to the rescue? Objective C blocks!
An anonymous function.. that can be OUTSIDE any #implementation, etc...
void doCFunction() { printf("You called me by Name!"); }
Then, in your objective-C method… you can somehow "get" the name, and "call" the function...
NSDictionary *functionDict = #{ #"aName" : ^{ doCFunction(); } };
NSString *theName = #"aName";
((void (^)()) functionDict[theName] )();
Result: You called me by Name!
Loves it! 👓 ⌘ 🐻

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?

How would I define a mix of Objective-C method parameters?

I would like to do something like this in my program:
[obj list error:&error];
But when I try to define the prototype/method, I get compile errors.
I've tried the following definitions:
-(void)list error:(NSError **)error;
-(void)list:() error:(NSError **)error;
nothing seems to work.
Why is the space between list and error in the method signature. If this is the prototype -
-(void) list_error:(NSError **)error;
list_error expects a pointers address to be passed to it. So, this should work.
[obj list_error:&ptr] ; // Assuming ptr is of type NSError* and is initialized.
I think, you are getting confused when to send more than one parameter to a method. Its simple. Method signature should be -
- ( return_type ) splitOne:(type) arg1 splitTwo:(type) arg2 ;
- indicates instance method. Same is the case for class method too but substitued a + instead of -. And so on the method name can be splitted.
Taking an example of fraction, to set a fraction it needs both numerator and denominator. So,
-(void) setNumerator: (int) n setDenominator: (int) d ;
And to call it -
[ obj setNumerator:10 setDenominator:20 ] ;
What is the need to split the method name ?
Normally, in C this function prototype would be -
void setFraction( int a, int b );
But when seeing the prototype, it isn't obvious whether a is numerator or denominator and is the same with b. That is the reason, why in Objective-C method name may be splitted into parts. In the above example of Objective-C, both the setNumerator and setDenominator forms the method name. And when calling, it's quite obvious to the user, the parameter being passed is what. Hope it helps to resolve your problem.

How to write a NSMutableArray of a struct type that also includes NSMutableArray inside of it?

I was wondering if there is any sample code out there for objective-C for implementing a NSMutableArray of type struct. Inside, I need there to be 2 mutable arrays (via NSMutableArray also) declared in the struct. All the code samples in my book show me how to make an array of defined size via C array syntax (with the brackets), but I don't know how to get one going with NSMutableArray. Has anyone else done this before? Here's my code so far...It compiles fine I have defined the size of the arrays (2 and 5 are used in my code below as an example, but I need to set it so I can have them mutable. I can work with simple structs when they just have some of the "easier-to-understand" data types like int, double, short, long, BOOL (you get the idea). When it gets into pointers though, this is where I become lost (I can use pointers fine, but knowing how to put them in a struct is the difficult part). Once the code is working with NSMutableArray's, would I put "network" in the interface as a pointer to type "Network"? I tried this before, but I got errors. In the end, I basically want to be able to write
network.input[2].list[1].value = 5.0;
on an arbitrarily defined array of type "Network". Could anyone offer suggestion or links to information about making a NSMutableArray of type "Network" which includes a struct of two NSMutableArray's? Thanks for any help!
SomeFile.h
#import <Foundation/Foundation.h>
struct lists{
double value;
};
// supporting structs
struct inputs{
struct lists list[2];
};
struct Network {
struct inputs input[5];
struct lists output[5];
}
#interface SomeFile : NSObject {
}
#end
SomeFile.m
#import "SomeFile.h"
#implementation SomeFile
#end
NSArray and NSMutableArray can only contain Objective-C objects, so you can't store structs in them. If the contents must be structs and you want something similar to NSArray, use NSPointerArray, available in 10.5 and later.
You can store pointers to Objective-C objects (like NSPointerArray* or id) inside a struct just like any other pointer type. For example, you could declare a struct for a doubly-linked list node that stores an Objective-C object like this:
typedef struct DoublyLinkedListNode {
id object;
__strong struct DoublyLinkedListNode *next;
__strong struct DoublyLinkedListNode *prev;
} DoublyLinkedListNode;
The __strong attribute is used in connection with garbage collection in Objective-C 2.0, since pointers to Objective-C objects act as strong references, but C pointer types do not by default. This way, as long as one node in the list is referenced from a __strong reference, the list won't disappear. (Read the Garbage Collection Programming Guide for details, and particularly the second half of Using Core Foundation with Garbage Collection.) You'll probably want to consider doing this for your structs.
As far as your desired syntax, I may not have fully understood your question, but you won't be able to use the bracket syntax to access objects in a Cocoa collections like an NSPointerArray. (Also, odds are you'll have to use the "->" operator instead of "." for the structs, since they're likely to be allocated on the heap. All Objective-C objects must be, and I assume you'll want to store these structs outside of the local scope of a method.)
Since Objective-C doesn't have generics, you also can't "implement [an] NSMutableArray of type struct". In fact, one of your previous SO questions has more detail on the subject. If that's not what you meant, feel free to clarify.
This is not be a complete answer; I’m not sure what you mean by not knowing how to put pointers in structs. I’m going to proceed by assuming you want to model an network of multiple inputs and outputs with a dynamic number of both.
You have a few choices here:
Use value objects instead of structs to store your values:
[[[network inputs] objectAtIndex:2] replaceObjectAtIndex:1 withObject:[NSNumber numberWithDouble:5.0]];
Model your Network with an object:
#interface Network : NSObject {
// ivars
}
- (void) setInput:(double)value atIndex:(NSInteger)valueIndex ofInputAtIndex:(NSInteger)inputIndex;
- (double) outputAtIndex:(NSInteger)index;
#end
Just use structs like you’re already doing; if you need to change the size up-front, use your friend malloc:
struct Network_value {
double value;
}
struct Network {
struct Network_value **inputs;
struct Network_value *outputs;
};
void Network_alloc(Network *n, unsigned inputs, unsigned input_values, unsigned outputs) {
n->outputs = calloc(sizeof(Network_value), outputs);
n->inputs = calloc(sizeof(Network_value *), inputs);
while (inputs --> 0) {
n->inputs[inputs] = calloc(sizeof(Network_value), input_values);
}
}
void Network_free(Network *n, unsigned inputs) {
free(n->outputs);
while (inputs --> 0) {
free(n->inputs[inputs]);
}
free(n->inputs);
}
Network network;
Network_alloc(&network, 5, 2, 5);
network.inputs[2][1].value = 5.0;
Network_free(&network, 2);
Combine ideas 2 and 3 by presenting a Network object but internally store the values with structs. This is probably a good idea if the number of inputs and outputs is very large.