Related
I have this problem. This the external library that i must use in .h file:
typedef struct _IPCSSContext IPCSSContext;
IPCSSContext * ipcssnew(const IPCSSCfg *_config, const IPCSSCallbacks *_callbacks, void *_user);
How can I use? Thanx
First you define a variable of type IPCSSCallbacks whatever that might be, but it's probably a struct of function pointers.
Then you fill in the fields of the variable with pointers to your callback functions.
Then you call icssnew() passing the IPCSSCallbacks, the config and a pointer to anything you like. This pointer will be passed untouched to your callback functions when they are called and you can do what you like with it in the callbacks (including nothing).
This is a pretty standard pattern in C for performing callbacks.
I realize 99% of you think "what the h***…" But please help me to get my head around the this concept of using pointers. I'm sure my specific question would help lots of newbies.
I understand what pointers ARE and that they are a reference to an adress in memory and that by using the (*) operator you can get the value in that address.
Let's say:
int counter = 10;
int *somePointer = &counter;
Now I have the address in memory of counter, and I can indirectly point to its value by doing this:
int x = *somePointer;
Which makes x = 10, right?
But this is the most basic example, and for this case I could use int x = counter; and get that value, so please explain why pointers really are such an important thing in Objective-C and some other languages... in what case would only a pointer make sense?
Appreciate it.
Objective-C has pointers because it is an evolution of C, which used pointers extensively. The advantage of a pointer in an object-oriented language like Objective-C is that after you create an object, you can pass around a pointer to the object instead of passing around the object itself. In other words, if you have some object that takes up a large amount of storage space, passing around a pointer is a lot more memory-efficient than passing around a copy of the object itself. This may not be noticeable in simple cases when you’re only dealing with primitive types like ints, but when you start dealing with more complex objects the memory and time savings are enormous.
More importantly, pointers make it much easier for different parts of your code to talk to each other. If variables could only be passed to functions “by value” instead of “by reference” (which is what happens when you use pointers), then functions could never alter their inputs. They could only change the state of your program by either returning a value or by changing a global variable—the overuse of which generally leads to sloppy, unorganized code.
Here’s a concrete example. Suppose you have an Objective-C method that will parse a JSON string and return an NSDictionary:
+ (NSDictionary *)parseJsonString:(NSString *)json
error:(NSError **)error;
The method will do the parsing and return an NSDictionary if everything goes okay. But what if there’s some problem with the input string? We want a way to indicate to the user (or at least to the programmer) what happened, so we have a pointer to a pointer to an NSError, which will contain that information. If our method fails (probably returning nil), we can dereference the error parameter to see what went wrong. What we’ve effectively done is to give our method two different kinds of return values: usually, it will return an NSDictionary, but it could also return an NSError.
If you want to read more about this, you may have better luck searching for “pointers in C” rather than “pointers in Objective-C”; pointers are of course used extensively in Objective-C, but all of the underlying machinery is identical to that of C itself.
What is the biggest advantage of using pointers in ObjectiveC
I'd say the biggest advantage is that you can use Objective-C at all - all Objective-C objects are pointers are accessed using pointers (the compiler and the runtime won't let you create objects statically), so you wouldn't get any further without them...
Item:
What if I told you to write me a program that would maintain a set of counters, but the number of counters would be entered by the user when he started the program. We code this with an array of integers allocated on the heap.
int *counters = malloc(numOfCounters * sizeof(int));
Malloc works with memory directly, so it by nature returns a pointer. All Objective-C objects are heap-allocated with malloc, so these are always pointers.
Item:
What if I told you to write me a function that read a file, and then ran another function when it was done. However, this other function was unknown and would be added by other people, people I didn't even know.
For this we have the "callback". You'd write a function that looked like this:
int ReadAndCallBack(FILE *fileToRead, int numBytes, int whence, void(*callback)(char *));
That last argument is a pointer to a function. When someone calls the function you've written, they do something like this:
void MyDataFunction(char *dataToProcess);
ReadAndCallBack(myFile, 1024, 0, MyDataFunction);
Item:
Passing a pointer as a function argument is the most common way of returning multiple values from a function. In the Carbon libraries on OSX, almost all of the library functions return an error status, which poses a problem if a library function has to return something useful to the programmer. So you pass the address where you'd like the function to hand information back to you...
int size = 0;
int error = GetFileSize(afilePath,&size);
If the function call returns an error, it is in error, if there was no error, error will probably be zero and size will contain what we need.
The biggest advantage of pointers in Objective-C, or in any language with dynamic allocation, is that your program can handle more items than the names that you invent in your source code.
If I declare an NSMutableString
NSMutableString *str_value;
Why do I have to declare this as a pointer (using *)? If I don't, I get a compilation error.
Could someone explain this clearly?
Recall that Objective C is a superset of C. When you declare a variable without * in C, it is an indication that the memory for that variable is allocated either in the automatic storage if it is a local variable, as part of its outer structure if it is a member of a structure, or in the static memory if it is a static or a global. Using the typename or a structure tag without * in a parameter list of a function indicates passing by value.
The designers of the Objective C language could have taken the Java-like route, making every class instance is a pointer without the pointer syntax, but then the readers of programs in Objective C would need to know if a name represents a typedef based on a struct or an id type to answer even the most basic questions about objects of that type, such as if it is implicitly passed by pointer or by value, if it is allocated as part of the owning structure or as a heap object pointed to by a pointer inside the structure, and so on.
To avoid this kind of confusion, designers of Objective C decided to preserve the explicit pointer syntax for id objects.
A pointer means you are pointing / referencing to that class. Yes it will cause a compilation error, the reason for a pointer is mainly for memory. One data type (int or BOOL or float etc...) is only a few bytes, therefore it is not necessary to have a pointer. But NSMutableString and other Objective-C classes have a lot of properties and methods, with a lot of code. Therefore, since in your apps will have a lot of objects, which will use a lot of memory and thus slow down your app/decrease performance. Of course you should release the object once you make a pointer.
Out of pure curiosity, I started playing with array's in ways that I have never used before. I tried making a data structure array, and set it equal to another:
typedef struct _test {
float value;
} test;
Simple enough struct, so I tried this:
test struct1[10];
test struct2[20];
struct1 = struct2;
I didn't think this would work, and it didn't even compile. But, this interests me a lot. Is it possible to take an array of 10 and increase the size to 20, while copying the data?
Objective-C
I am actually doing this with Objective-C, so I'd like to hear from the Objective-C people as well. I want to see if it is possible to change the size of struct1 in this file.
#interface Object : NSObject {
test struct1;
}
Remember: This is only out of curiosity, so everything is open to discussion.
Something else that is not exactly pertinent to your question but is interesting nonetheless, is that although arrays cannot be assigned to, structs containing arrays can be assigned to:
struct test
{
float someArray[100];
};
struct test s1 = { /* initialise with some data*/ };
struct test s2 = { /* initialise with some other data */ };
s1 = s2; /* s1's array now contains contents of s2's array */
This also makes it possible to return fixed-length arrays of data from functions (since returning plain arrays is not allowed):
struct test FunctionThatGenerates100Floats(void)
{
struct test result;
for (int i = 0; i < 100; i++)
result.someArray[i] = randomfloat();
return result;
}
As others have said, arrays allocated like that are static, and can not be resized. You have to use pointers (allocating the array with malloc or calloc) to have a resizable array, and then you can use realloc. You must use free to get rid of it (else you'll leak memory). In C99, your array size can be calculated at runtime when its allocated (in C89, its size had to be calculated at compile time), but can't be changed after allocation. In C++, you should use std::vector. I suspect Objective-C has something like C++'s vector.
But if you want to copy data between one array and another in C, use memcpy:
/* void *memcpy(void *dest, const void *src, size_t n)
note that the arrays must not overlap; use memmove if they do */
memcpy(&struct1, &struct2, sizeof(struct1));
That'll only copy the first ten elements, of course, since struct1 is only ten elements long. You could copy the last ten (for example) by changing &struct2 to struct2+10 or &(struct2[10]). In C, of course, not running off the end of the array is your responsibility: memcpy does not check.
You can also you the obvious for loop, but memcpy will often be faster (and should never be slower). This is because the compiler can take advantage of every trick it knows (e.g., it may know how to copy your data 16 bytes at a time, even if each element is only 1 byte wide)
You can't do this in C with static arrays, but you can do it with dynamically allocated arrays. E.g.,
float *struct1, *struct2, *struct3;
if(!(struct1 = malloc(10 * sizeof(float))) {
// there was an error, handle it here
}
if(!(struct2 = realloc(struct1, 20 * sizeof(float))) {
// there was an error, handle it here
// struct1 will still be valid
}
if(!(struct3 = reallocf(struct2, 40 * sizeof(float))) {
// there was an error, handle it here
// struct2 has been free'd
}
In C, I believe that's a good place to use the realloc function. However, it will only work with dynamically allocated arrays. There's no way to change the memory allocated to struct1 by the declaration test struct1[10];.
In C arrays are constants, you can't change their value (that is, their address) at all, and you can't resize them.
Clearly if you declare your array with a fixed size, test struct1[10] then it cannot be resized. What you need to do is to declare it as a pointer:
test *struct1;
Then you must use malloc to allocate the array and can use realloc to resize it whilst preserving the contents of the original array.
struct1 = malloc(10*sizeof(*struct1));
//initialize struct1 ...
test *struct2 = realloc(struct1, 20*sizeof(*struct1));
If you're using Objective C, you know you can just use NSMutableArray, which automatically does the realloc trick to reallocate itself to store however many objects you put in it, up the limit of your memory.
But you're trying to do this with struct? What would that even mean? Suppose you increase the amount of memory available to struct1 in Object. It's still a struct with one member, and doesn't do anything more.
Is the idea to make Object be able to contain an expanded struct?
typedef struct _test2 {
float value;
NSObject *reference;
} test2;
But then you still can't access reference normally, because it's not a known part of Object.
Object *object2;
...
NSLog(#"%#", object2.struct1.reference); // does not compile
If you knew you had one of your modified objects, you could do
Object *object2;
...
NSLog(#"%#", ((test2)(object2.struct1)).reference);
And also you could still presumably pass object2 to anything that expects an Object. It only has any chance of working if struct1 is the last member of Object, and don't mess with subclassing Object either.
Some variety of realloc trick might then work, but I don't think realloc in particular, because that's intended to be used on objects that are allocated with malloc, and the details of what C function is used to allocate objects in not exposed in Objective C, so you shouldn't assume it's malloc. If you override alloc then you might be able to make sure malloc is used.
Also you have to watch out for the fact that it's common in Objective C for more than one pointer to an object to exist. realloc might move an object, which won't be semantically correct unless you correct all the pointers.
I've tried to use id to create duck typing in objective-c. The concept looks fine in theory but failed in practice. I was unable to use any parameters in my methods. The methods were called but parameters were wrong. I was getting BAD_ACESS for objects and random values for primitives. I've attached a simple example below.
The question:
Does any one knows why the methods parameters are wrong?
What is happening under the hood of the objective-c?
Note: I'm interest in the details. I know how to make the example below work.
An example:
I've created a simple class Test that is passed to an other class using property id test.
#implementation Test
- (void) aSampleMethodWithFloat:(float) f andInt: (int) i {
NSLog(#"Parameters: %f, %i\n", f, i);
}
#end
Then in the class the following loop is executed:
for (int i=0; i < 10; ++i) {
float f=i*0.1f;
[tst aSampleMethodWithFloat:f andInt:i]; // warning no method found.
}
Here is the output that I'm getting. As you can see the method was called but the parameters were wrong.
Parameters: 0.000000, 0
Parameters: -0.000000, 1069128089
Parameters: -0.000000, 1070176665
Parameters: 2.000000, 1070805811
Parameters: -0.000000, 1071225241
Parameters: 0.000000, 1071644672
Parameters: 2.000000, 1071854387
Parameters: 36893488147419103232.000000, 1072064102
Parameters: -0.000000, 1072273817
Parameters: -36893488147419103232.000000, 1072483532
Update:
I've found out by accident that when I add a declaration of aSampleMethodWith... to the class with for loop the warning disappears and the method on the Test class is called correctly.
Update 2:
As pointed out by JeremyP the direct cause of the problem is that the floats are treated as doubles. But anyone knows why? (following the 5why principle :) ).
According to #eman the call is translated to simple C function call and compiler directive to get the SEL. So the #selector gets confused. But why? The compiler have all necessary type informations in the first method call. Does any one knows a good source of information about the Objective-C internals I've search The Objective-C Programming Language but i didn't find the answer.
By default floating point values are passed as doubles, not floats. The compiler does not know, at the point where [tst aSampleMethodWithFloat:f andInt:i]; occurs that it is only supposed to pass a float, so it promotes f to a double. This means that, in the method, when the compiler does know it is dealing with a float, f is the float formed by the first four bytes of the double passed to the method and i is an int formed from the second four bytes of the double passed.
You can fix this by either
changing the first parameter of aSampleMethodWithFloat:andInt: to a double
importing the interface declaration of Test into the file where you use it.
NB there is no gain except a small amount of space when using floats in C. You might as well use doubles everywhere.
I think JeremyP is correct about the problem being about doubles vs floats. As for implementation details, message dispatch in Objective-C uses the objc_msgSend(id theReceiver, SEL theSelector, ..) C function (for some deep nitty-gritty, see here). You can simulate the same results of method dispatch like so:
SEL theSelector = #selector(aSampleMethodWithFloat:andInt:);
objc_msgSend(self.test, theSelector, 1.5f, 5);
SEL is just a number that corresponds to a function (that is dynamically determined based on the method signature). objc_msgSend then looks up the actual function pointer (of type IMP) of the method and invokes it. Since objc_msgSend has a variable number of arguments, it will just use as many as you pass in. If you were to do:
objc_msgSend(self.test, theSelector, 1.5f);
It would use 1.5f correctly and have junk for the other variable. Since the method signature typically denotes the number of arguments, this is hard to do under normal usage.
You can make the warning go away by making a category like this:
#interface NSObject (MyTestCategory)
- (void) aSampleMethodWithFloat:(float) f andInt: (int) i;
#end
Without a signature available at the calling point, it isn't known what type the parameters are supposed to have. Undefined methods will be assumed to take ... as parameters, which isn't what yours does. If there is any interface seen by the compiler at this point, where the method in question exists, that definition will be used.
The trouble here is with the dividing line between C and Objective-C. The id type specifies any object, but ints and floats are not objects. The compiler needs to know the C type of all the arguments and the return type of any method you call. Without a declaration, it assumes that a method returns id and takes an arbitrary number of id arguments. But id is incompatible with int and float, so the value doesn't get passed correctly. That's why it works correctly when you provide a declaration — then it knows your int is an int and your float is a float.