using static c variables in Objective C classes - objective-c

i have helper C functions in some Objective C classes.
Just found out that the values of global, static C variables which i use in these functions are shared between instances of the class (duh), which is not what i want.
Is there a way to declare these variables local to instances of the class, so that they are visible by the helper functions without passing them explicitly?

Is there a way to declare these variables local to instances of the class
Sure, make them instance variables.
But:
so that they are visible by the helper functions without passing them explicitly?
You can pass the object into the function. If you have appropriate accessors, the function can get them. And if you have mutators, it can modify them, too.
But if you're doing that, you might as well just create a method, and automatically have access to the instance variables.

want to avoid method calls where necessary
logically separate it so your low level code is in c or c++, then add the required data to your objc class:
/* c example */
typedef struct t_generator {
UInt32 a;
} t_generator;
static void Generate(t_generator* const gen) {
/.../
}
#interface MONObjCGeneratorContainer : NSObject
{
t_generator generator;
NSString * name;
UInt32 b;
}
#end
if the data interface is as simple you can just access them from the instance:
- (void)method { GenerateB(&b); }
that should meet all the requirements you have posted (so far).

Related

Assign selector to C function in Objective-C without callback

I am attempting a method swizzle in Obj-C but I would like to pass it a pure C function. This means I need to somehow assign a selector and/or manually build an objc_method struct. Maybe somehow leverage NSInvocation?
My understanding is that due to the fact that Obj-C is a strict superset of C and therefor fully compatible.
What I have going now:
main.m :
#include....
CFStringRef strRet(void) {
return CFSTR("retString");
}
int main(int argc, const char * argv[]) {
#autoreleasepool {
SEL _strRet = sel_registerName("strRet");
//I also tried: SEL _strRet = NSSelectorFromString(#"strRet");
Class bundle = objc_getClass("NSBundle");
method_exchangeImplementations(
class_getInstanceMethod(bundle, sel_registerName("anySelector")),
class_getInstanceMethod(bundle, sel_registerName("_strRet")
);
I have tried putting the C function inside #implementation (which I would like to avoid) and even then it did not work.
You can't swizzle a C function per se; swizzling is based on method lookup which goes through method descriptions (which are represented by the Method type by the runtime functions) and C functions do not have a method description.
However the implementation of a method is just a C function. Such a C function must take a minimum of two arguments, being the object the method is invoked on (the Objective-C implicit parameter self) and the selector (the Objective-C implicit parameter _cmd). When you swizzle a method the replacement implementation, a C function, must have exactly the same type as the original – complete with the two implicit arguments – so your strRet() would not be suitable as is, you would need to change it to:
CFStringRef strRet(NSObject *self, CMD sel, void)
{
return CFSTR("retString");
}
So you have three main choices:
The easiest way is to define a method whose body is your "pure" C function, then swizzle the recommended way (taking care to handle inheritance correctly, see this answer).
If you really want to write a C function and that C function does not need to call the original implementation of the method then:
(a) You need to convert your C function into one which can be used as a method implementation. You can:
If you are writing/have the source of the C function you simply define it to take the two implicit arguments as above. Take the address of this function and cast it to IMP, which is just a typedef for a C function pointer of the appropriate type, for use below.
If you are using a C function whose definition you cannot change then you can do one of:
Write a C wrapper function which takes the extra arguments, ignores them and calls your target C function. Take the address of this wrapper function and cast it to IMP for use below.
Wrap the call to your C function in a block and use imp_implementationWithBlock() to produce an IMP value from it. You can read this article for a description of using imp_implementationWithBlock().
(b) use method_setImplementation() to set the implementation to the IMP value you produced in (a).
If you really want to write a C function and that C function does need to call the original implementation of the method then you will need to add a method to your class whose implementation is your C function – modified/wrapped as in (2), then swizzle your added method with your original method as under (1) so that the original implementation is still available as a method. To add a method you use class_addMethod()
HTH
The key here is finding a mechanism that maps between the function pointer and your context. The simplest way to do that is by generating a new function pointer. You can use imp_implementationWithBlock(), MABlockClosure, or roll your own.
The simplest mechanism to create a new function pointer I've found is to remap the entire function to a new address space. The new resulting address can be used as a key to the required data.
#import <mach/mach_init.h>
#import <mach/vm_map.h>
void *remap_address(void* address, int page_count)
{
vm_address_t source_address = (vm_address_t) address;
vm_address_t source_page = source_address & ~PAGE_MASK;
vm_address_t destination_page = 0;
vm_prot_t cur_prot;
vm_prot_t max_prot;
kern_return_t status = vm_remap(mach_task_self(),
&destination_page,
PAGE_SIZE*(page_count ? page_count : 4),
0,
VM_FLAGS_ANYWHERE,
mach_task_self(),
source_page,
FALSE,
&cur_prot,
&max_prot,
VM_INHERIT_NONE);
if (status != KERN_SUCCESS)
{
return NULL;
}
vm_address_t destination_address = destination_page | (source_address & PAGE_MASK);
return (void*) destination_address;
}
Note that page_count should be large enough to contain all of your original function. Also, remember to handle pages that aren't required anymore and note that it takes a lot more memory per invocation than MABlockClosure.
(Tested on iOS)

Having trouble accessing variable

I want to find the address of one of the structure's data members, but I'm having trouble accessing its variables. Is there of a solution that donesn't require me to change the struct in any way?
h file
class C
{
private:
int x;
char b;
};
cpp file.
char *p2 = new char[128];
memset(p2,'aa',128);
Test_C *r2 = new(p2) Test_C[3];
//inside for loop
printf("Address: 0x%x, Value of b: %x \n",&r2[i]->b, r[i].r=0x50);
I'm getting the error at &r2[i]->b;
Also some code review would be nice :) I'm planing on outputting values of the C struct with padding
It seems you have posted a C++ class and not a C struct.
From here:
private members of a class are accessible only from within other
members of the same class or from their friends.
So, to answer your question, you cannot access those private members from outside the class without modifying the class itself (to include public accessors, for instance).

Can a C function be defined within an Objective-C method?

I have a method, like so:
- (void) simpleMethod {
var = someValue;
}
I wanted to define a function which exists only within that method (I can do this in python for example). I tried to define it like a normal C function, like this...
- (void) simpleMethod {
var = someValue;
int times1k(int theVar) {
return theVar * 1000;
}
ivar = times1k(var);
}
But Xcode throws various errors. Is it possible to define a function within a method in Objective-C? And if so, how?
No, Objective-C follows the strict C rules on this sort of thing, so nested functions are not normally allowed. GCC allowed them via a language extension but this extension has not been carried over to Clang and the modern toolchain.
What you can do instead is use blocks, which are Objective-C's version of what Python (and most of the rest of the world) calls closures. The syntax is a little funky because of the desire to remain a superset of C, but your example would be:
- (void) simpleMethod {
var = someValue;
// if you have a bunch of these, you might like to typedef
// the block type
int (^times1k)(int) = ^(int theVar){
return theVar * 1000;
};
// blocks can be called just like functions
ivar = times1k(var);
}
Because that's a closure rather than a simple nested function there are some rules you'd need to follow for declaring variables if you wanted them not to be captured at their values when the declaration is passed over, but none that are relevant to your example because your block is purely functional. Also times1k is a variable that you can in theory pass about, subject to following some unusual rules about memory management (or letting the ARC compiler worry about them for you).
For a first introduction to blocks, I like Joachim Bengtsson's article.

class variable scope issue with objc / cocoa?

Compiling in XCode 3.1.3 using GCC 4, under Leopard 10.5.8, with 10.5 as my target...
I have an interface, thus:
#interface testThing : NSObject { classContaininghooHa *ttv; }
#end
And an implementation, thus:
#implementation: testThing
- (void) instanceMethodMine
{
[ttv hooHa]; // works perfectly, compiles, links, hooHa is invoked.
}
// void cFunctionMine()
// {
// [ttv hooHa]; // compiler: 'ttv' undeclared (first use in this function) "
// }
void stupidCFunctionMine((testThing *)whom) // whom is passed class 'self' when invoked
{
[whom instanceMethodMine]; // compiles, links, works. :/
}
#end
Now, my understanding -- clearly flawed -- was that if you declared a variable, class ID or otherwise, it was private to the class, but within the class, is performed essentially as a global, stored in the allocated class instance for the duration of its existence.
That's how it acts for objc methods.
But in the c function above, also written within the class, the variable appears to be invisible. The doesn't make sense to me, but there it is.
Can someone explain to me what is going on?
While you're at it, how can I declare this as an instance variable so I can use the method within a c function declared within the class scope as shown above, as well as within methods?
Insight much appreciated.
It doesn't make any difference where you are declaring/defining your "normal" c functions. They are not part of the class, they are just plain old c functions. No connection to the class whatsoever. Passing the instance they work on is a workaround if you really don't want to make this function a true objective-c method.
interface methods have full access to it's member variables. And the C function is not part of the class and so it cannot access any class variables unless it takes an class instance as the argument.
void cFunctionMine()
{
[ttv hooHa]; // compiler: 'ttv' undeclared (first use in this function)
}
Clearly cFunctionMine is not part of the interface. So it does not what ttv is to send the message hooHa.
While you're at it, how can I declare this as an instance variable so I can use the method within a c function declared within the class scope as shown above, as well as within methods?
void cFunctionMine()
{
// 1. Create an instance using alloc and init
testThing *ttv = [ [testThing alloc] init ] ;
[ttv hooHa] ;
// Now the above statement is valid. We have a valid instance to which
// message can be passed to.
// .....
[ ttv release ] ;
// release the resources once you are done to prevent memory leaks.
}

What can I do if two methods call each other and I don't want to make one of them public in the header file?

I have two methods -a and -b.
-a calls sometimes -b, and -b sometimes calls -a. Both methods are intended to be private, and not called from outside.
But I had to make one of them public in the .h file, because otherwise the compiler would go crazy and give a warning for either one of them.
Is there any valid and good-practise solution for that problem?
Traditionally, what you'd do is define a category (something like #interface MyClass (MyClass_Private) inside the implementation file that declares the private methods. Apple recently introduced a feature called a class extension that is intended for this exact case. It's basically a specialization of a category, but the class has to implement the methods when it's first defined. It looks like:
#interface MyObject ()
- (void)setNumber:(NSNumber *)newNumber;
#end
Implement a protocol.
or
Write a second header file with a category.
If you really want the functions to be private, you need to declare them as static. To eliminate the cyclic dependency, one should be declared before the other is defined. Here's a simple example:
static void b(); /* forward declaration */
static void a()
{
if (foo)
b(); /* forward-declared, so we're ok */
}
static void b()
{
if (bar)
a(); /* already defined, so we're ok */
}
This is all valid C, and so based on the OP's comment I assume this is valid ObjC as well.