qsort on an array of pointers to Objective-C objects - objective-c

I have an array of pointers to Objective-C objects. These objects have a sort key associated with them. I'm trying to use qsort to sort the array of pointers to these objects. However, the first time my comparator is called, the first argument points to the first element in my array, but the second argument points to garbage, giving me an EXC_BAD_ACCESS when I try to access its sort key.
Here is my code (paraphrased):
- (void)foo:(int)numThingies {
Thingie **array;
array = malloc(sizeof(deck[0])*numThingies);
for(int i = 0; i < numThingies; i++) {
array[i] = [[Thingie alloc] initWithSortKey:(float)random()/RAND_MAX];
}
qsort(array[0], numThingies, sizeof(array[0]), thingieCmp);
}
int thingieCmp(const void *a, const void *b) {
const Thingie *ia = (const Thingie *)a;
const Thingie *ib = (const Thingie *)b;
if (ia.sortKey > ib.sortKey) return 1; //ib point to garbage, so ib.sortKey produces the EXC_BAD_ACCESS
else return -1;
}
Any ideas why this is happening?

The problem is two fold:
the first argument to qsort needs to be a pointer to the beginning of the array
the arguments passed to your sort function are actually pointers to the pointers of your data
Consider this working code:
int thingieCmp(const void *a, const void *b) {
NSObject *aO = *(NSObject **)a;
NSObject *bO = *(NSObject **)b;
if (aO.hash > bO.hash) return 1;
else return -1;
}
int main (int argc, const char * argv[]) {
NSObject **array;
array = malloc(sizeof(NSObject*)*20);
for(int i = 0; i < 20; i++) {
array[i] = [NSObject new];
}
qsort(array, 20, sizeof(NSObject*), thingieCmp);
return 0;
}
Note that the comparison function resolves the data pointers by NSObject *aO = *(NSObject **)a and the qsort function takes array as an argument directly.
All of this, though, begs the question of Why bother?
NSArray is very good at holding arrays of objects and is quite conveniently sortable. Performance is excellent in the general case. If performance analysis indicates that it isn't, you can optimize it away relatively easily.
Note, also, that I have been consistent in use of sizeof() -- same type in both places. Also, the const in your original code is not necessary.

I think, one mistake lies right in the line
qsort(array[0], numThingies, sizeof(array[0]), thingieCmp);
Try
qsort(&array[0], numThingies, sizeof(array[0]), thingieCmp);
or even
qsort(array, numThingies, sizeof(array[0]), thingieCmp);
instead. The compiler won't complain here, as qsort is supposed to take a void* and you pass it a Thingy* which can legally be cast to void* without warning, but you really want qsort to operate on the entire array, which has type Thingy**.
Another thing is: the comparator will be called with pointers to the array slots as arguments, so what you get is actually a Thingy**:
int
thingieCmp(void* a, void* b)
{
Thingie *ia = *((Thingie**)a);
Thingie *ib = *((Thingie**)b);
...
}

Related

Pass Objective-C block or method as C-function pointer

I'm using https://github.com/nodejs/http-parser, the callbacks it uses are like this
struct http_parser_settings {
http_cb on_message_begin;
http_data_cb on_url;
http_data_cb on_status;
http_data_cb on_header_field;
http_data_cb on_header_value;
http_cb on_headers_complete;
http_data_cb on_body;
http_cb on_message_complete;
/* When on_chunk_header is called, the current chunk length is stored
* in parser->content_length.
*/
http_cb on_chunk_header;
http_cb on_chunk_complete;
};
The main callback type is defined here
typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
I'm trying to find a way to pass either an Objective-C block or method as the function pointer in the parser_settings. However it lets me use only a C-function, which doesn't suit me because I also need to access the state of an Objective-C object in the callback
At the moment my solution is as follows:
int onHeaderField(http_parser* _, const char* at, size_t length) {
// Need to access state here, so doesn't work for me as a c function
char header[length];
strncpy(header, at, length);
NSLog(#"Header %s", header);
return 0;
}
...
- (void)method {
http_parser_settings settings;
settings.on_header_field = onHeaderField; // rather than func would like to set a block/method to capture and access self
size_t nparsed = http_parser_execute(self.parser, &parserSettings, charData, messageLength)
}
How would I go about accessing self from the callback passed to http_parser_execute?
Technically you can "extract" an Objective-C method implementation in form of a C-pointer with use of class_getMethodImplementation, however these implementations have objc_msgSend-like signature and always require the receiver as an argument, thus not really usable outside of Objective-C world:
NSString *str = #"Hollow World";
SEL sel = #selector(isEqualToString:);
Method meth = class_getInstanceMethod([str class], sel);
typedef BOOL(*IsEqualToStringPtr)(NSString *, SEL, NSString *);
IsEqualToStringPtr impl = (IsEqualToStringPtr)method_getImplementation(meth);
NSLog(#"Is equal? %#", impl(str, sel, #"Hello, World!") ? #"YES" : #"NO"); // prints "NO"
NSLog(#"Is equal? %#", impl(str, sel, #"Hollow World") ? #"YES" : #"NO"); // prints "YES"
Having that said, neither blocks nor Objective-C methods are directly convertible to a C function pointer (they are pointers to structures under the hood), especially when you want to complement it with any kind of context/state.
The simplest thing you can do is to use a global/statically allocated block variable which can be accessed from a C function without altering it's signature:
static int(^StaticBlock)(http_parser *parser, const char *at, size_t length);
static int my_callback(http_parser *parser, const char *at, size_t length) {
return StaticBlock(parser, at, length);
}
...
- (void)someObjectiveCMethod {
__weak typeof(self) weakSelf = self;
StaticBlock = ^(http_parser *parser, const char *at, size_t length) {
if (!weakSelf) {
return -1;
}
__strong typeof(weakSelf) strongSelf = weakSelf;
strongSelf.mprpty += length;
NSLog(#"Hello from Objective-C");
return 8;
};
http_parser_settings settings;
settings.on_header_field = my_callback;
}
The only viable alternative I can think of is using C++ lambdas. However it's still a big challenge when you need to access current state/context, let alone it will require you to switch to Objective-C++. If you are ok with it, first you need to rename your Objective-C file from SomeClass.m into SomeClass.mm. This way you tell Clang that the source code is Objective-C++ now and the compiler should accept a C++ code. Next, if your C library doesn't have C++ guards, you may want to wrap the C includes with extern "C" expression (otherwise linker would not be able to locate C symbols, because C++ mangles them):
extern "C" {
#include <c_header.h>
}
Now the tricky part: lambda expressions return special objects, closures, which can be seamlessly converted to C function pointers only if they don't capture anything from surrounding context. In our scenario it's not the case and it will require extra steps to convert it to a C pointer. Add this code somewhere in your *.mm file:
template<typename L>
struct c_functor_factory : c_functor_factory<decltype(&L::operator())> {};
template<typename R, typename F, typename ...Args>
struct c_functor_factory<R(F::*)(Args...) const> {
using pointer = typename std::add_pointer<R(Args...)>::type;
static pointer make_cptr(F&& func) {
static F instance = std::forward<F>(func);
return [](Args... args) {
return instance(std::forward<Args>(args)...);
};
}
};
template<typename L>
inline static typename c_functor_factory<L>::pointer make_cptr(L&& lambda) {
return c_functor_factory<L>::make_cptr(std::forward<L>(lambda));
}
In fact this solution is not much far from the global C function solution I suggested above. When a closure is passed as an argument here, this template function just perfect-forwards it to a statically allocated variable. As a result the static closure can be called from a capture-less lambda, which in turn is converted to a C function pointer.
Finally, you can make use of C++ lambda expressions and pass them as C function pointers anywhere in your Objective-C code:
- (void)someObjectiveCMethod {
__weak typeof(self) weakSelf = self;
const auto cptr = make_cptr([weakSelf](http_parser *parser, const char *at, size_t length) {
if (!weakSelf) {
return -1;
}
__strong typeof(weakSelf) strongSelf = weakSelf;
strongSelf.num += val;
NSLog(#"Hello from Objective-C++, %s!", at);
return 32;
});
http_parser_settings settings;
settings.on_header_field = my_callback;
}
Unlike the previous one, C++ solution is much more reliable, because each time your code hits the lambda expression, it emits a new closure object. In both cases, however, the function objects have static storage duration, thus make sure you don't pass any strong pointer in the body of it (otherwise it will never be released).

float array gives different datas at the end of it in objective c

I bumped to a strange error.(at least for me) I am trying to use float array in FFT and audio filters that I apply. but float array gives different datas at the end.
I define a global pointer. I point a float array to it. but when I try to use the pointer in somewhere out of the scope of a method, the last 100-150 datas of 441000 datas get mostly 0 or some other very big numbers. I dont understand how a data can change when I use somewhere in out of scope
in scope I loop in it and every data is correct but when I try to loop outside of the scope of the method I created the array, it gives different datas at the end.
#interface ViewController ()
{
float *filteredData;
int theFileLengthInFrames;
}
#end
#implementation ViewController
..
..
-(void)FilterData:(float * ) rawData
{
int count = theFileLengthInFrames;
float filteredRawData[count];
for (int i = 0; i<count; i++)
{
filteredRawData[i] = rawData[i];
printf("%d_%f ",i,filteredRawData[i]);
//I check here to see the data . In here it is normal
}
filteredData = filteredRawData;
}
-(void) CalculateFFT
{
int numSamples = theFileLengthInFrames;
for (int i = 0; i<numSamples; i++)
{
printf("%d_%f ",i,filteredData[i]);
//when I check here to see the data , the last around 100 data are 0.00000 or some big number such as 250399682724883753288597504.000000
}
}
need help thanks
Your FilterData: method points the instance variable filteredData to a local array filteredRawData. Since filteredRawData is allocated on the stack, it becomes invalid when FilterData: returns. Then filteredData is a dangling pointer, and using it results in undefined behavior.
Solution: allocate persistent storage for filteredData. I would do it like this:
#implementation ViewController {
NSMutableData *filteredDataStorage;
float *filteredData;
}
-(void)FilterData:(float * ) rawData {
int count = theFileLengthInFrames;
filteredDataStorage = [NSMutableData dataWithLength:count * sizeof *rawData];
filteredData = (float *)filteredDataStorage.mutableBytes;
for (int i = 0; i<count; i++) {
filteredRaw[i] = rawData[i];
printf("%d_%f ",i,filteredRawData[i]);
//I check here to see the data . In here it is normal
}
}
Using NSMutableData for the persistent storage lets ARC take care of deallocating it when you call FilterData: again, or when ViewController is deallocated.
filteredData - The float pointer is an ivar, it's scoped to your object instance.
filteredRawData is defined at method scope. It's an array located on the stack. When filteredRawData goes out of scope that memory is no longer valid. Reading from it is undefined at best and could result in an access violation. You probably want to use malloc to dynamically allocate memory for your data, or have a global buffer defined for you to play with.

How to return a C-style array of integers in Objective-C?

How to return a C-style array of integers from an Objective-C method? This is what my code looks like so far:
Function call:
maze = [amaze getMaze];
Function:
-(int*) getMaze{
return maze;
}
I just started writing in Objective-C today so this is all new to me.
In C if you need to return an array from a function, you need to allocate memory for it using malloc and then return the pointer pointing to the newly allocated memory.
Once you're done working with this memory you need to free it.
Something like:
#include <stdlib.h> /* need this include at top for malloc and free */
int* foo(int size)
{
int* out = malloc(sizeof(int) * size); /* need to get the size of the int type and multiply it
* by the number of integers we would like to return */
return out; /* returning pointer to the function calling foo().
* Don't forget to free the memory allocated with malloc */
}
int main()
{
... /* some code here */
int* int_ptr = foo(25); /* int_ptr now points to the memory allocated in foo */
... /* some more code */
free(int_ptr); /* we're done with this, let's free it */
...
return 0;
}
This is as C style as it gets :) There are probably other (arguably more suitable) ways to do this in Objective C. However, as Objective C is considered a strict superset of C, this would also work.
If I may further expand on the need to do this by pointers. C-style arrays allocated in a function are considered local, once the function is out of scope they are automatically cleaned up.
As pointed out by another poster, returning a standard array (e.g. int arr[10];) from a function is a bad idea as by the time the array is returned it no longer exists.
In C we get around this problem by allocating memory dynamically using malloc and having a pointer that points to that memory returned.
However unless you free this memory adequately, you may introduce a memory leak or some other nasty behavior (e.g. free-ing a malloc-ed pointer twice will produce unwanted results).
Given you explicitly ask about C-style arrays no suggestions here that you should use NSArray etc.
You cannot return a C-style array directly (see below) as a value in Objective-C (or C or C++), you can return a reference to such an array.
Types such as int, double and struct x can all be passed by value - that is the actual bits representing the value are passed around. Other things; such as C-style arrays, dynamically allocated memory, Objective-C style objects, etc.; are all passed by reference - that is a reference to a location in memory that contains the actual bits the represent the value is passed around.
So to return a C-style array from a function/method you can:
Dynamically (malloc et al) an array and return the reference to the allocated memory;
Pass in a reference to an already existing array and have the function fill it up; or
Wrap the array up as a struct...
The normal choices are (1) or (2) - note you cannot return a reference to a stack allocated array, as in:
int *thisIsInvalid()
{
int myValues[5];
...
return myValues; // will not work, the type is correct but once function
// returns myValues no longer exists.
}
If you really want to return a (small) array by value you can actually do it using (3). Remember that struct values are passed by value. So the following will work:
typedef struct
{
int array[5];
} fiveInts;
fiveInts thisIsValid()
{
fiveInts myValues;
...
myValues.array[3] = ...; // etc.
...
return myValues;
}
(Note that there is no overhead from wrapping the array inside a struct when it comes to reading/writing the array - the cost in the above is copying all the values back - hence only advised for small arrays!)
HTH
- (NSArray *)toArray:(int *)maze {
NSMutableArray *retVal = [[NSMutableArray alloc] init];
for (int c = 0; maze[c] != NULL; c++) {
[retVal addObject:[NSNumber numberWithInt:maze[c]]];
}
return [retVal array];
}
I've never been comfortable passing mutable data in and out of methods and not sure why. If you need to change the values later, send the array a mutableCopy message.
you can do it in this way
- (void)getArray:(int *)array withLength:(NSUInteger)length{
for (int i = 0; i < length; i++)
array[i] = i;
}
int array[3];
[object getArray:array withLength:3];
NSLog(#"%d %d %d", array[0], array[1], array[2]); // 1 2 3

Why can I modify a const __restrict pointer but not a typdef'd version?

Note: I'm using the objective C compiler that ships with the latest version of Xcode.
Why is it that this is legal:
void verySpecial(const float* __restrict foo, const int size) {
for (int i = 0; i < size; ++i) {
// ... do special things ...
++foo; // <-- Should be illegal to modify const pointer?
}
}
However, if I use a typedef, it does what I think it should do.
typedef float* __restrict RFloatPtr;
void verySpecial(const RFloatPtr foo, const int size) {
for (int i = 0; i < size; ++i) {
// ... do special things ...
++foo; // <-- Now this is a compiler error.
}
}
So, what is different in the typedef'd case, and what don't I understand? Reading about __restrict makes my brain hurt, and I'm not even sure it matters here.
++foo; // <-- Should be illegal to modify const pointer?
Yap. Modifying a const pointer is illegal. However, modifying a non-const pointer to something which is const isn't. I think you're confusing
const float *foo
with
float *const foo
Also, of course you can't modify a restrict pointer, because it doesn't make sense. restrict tells the compiler that the pointer is guaranteed not to overlap with other pointers. This assumption may no longer be true if you decrement or increment the pointer.

Fast Enumeration Vs NSEnumerator in Objective-C

I have seen this over and over, why exactly is it faster to use fast enumeration in loops rather than an NSEnumerator using nextObject:.
NSEnumerator is the old way to enumerate over collections. It involves creating an object to represent the enumeration, then calling a method on it for every single iteration. While this was perfectly serviceable for many years, it's not terribly efficient, as it involves at least one message send for every iteration of the loop. NSFastEnumeration is the more modern approach, which leverages native language support to provide a much more efficient enumeration. The way it works under the hood is it creates a struct that represents the current enumeration state and repeatedly calls -countByEnumeratingWithState:objects:count: on the collection. This method returns a C array of objects in the objects out-param as well as a counter in the count out-param. This allows the caller to then iterate over the C array. In essence, this means one message call per chunk of objects, which, depending on the collection, could be as efficient as a single message call to get all objects.
If you have a bit of code that looks like
for (id obj in myArray) {
[obj doSomething];
}
This gets translated by the compiler into something roughly equivalent to
NSFastEnumerationState __enumState = {0};
id __objects[MAX_STACKBUFF_SIZE];
NSUInteger __count;
while ((__count = [myArray countByEnumeratingWithState:&__enumState objects:__objects count:MAX_STACKBUFF_SIZE]) > 0) {
for (NSUInteger i = 0; i < __count; i++) {
id obj = __objects[i];
[obj doSomething];
}
}
The actual variables used are hidden, and the maximum size of the object buffer is also implementation-dependent, but the basic idea is there. It translates iteration over an obj-c collection into iteration over a C array.
GCC 8.9.4 Fast enumeration
protocol
GNUstep libs/base/trunk/Source/NSEnumerator.m countByEnumeratingWithState:objects:count:
It is not same as Apple's implementation but it is helpful to understand.
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state
objects: (id*)stackbuf
count: (NSUInteger)len
{
IMP nextObject = [self methodForSelector: #selector(nextObject)];
int i;
state->itemsPtr = stackbuf;
state->mutationsPtr = (unsigned long*)self;
for (i = 0; i < len; i++)
{
id next = nextObject(self, #selector(nextObject));
if (nil == next)
{
return i;
}
*(stackbuf+i) = next;
}
return len;
}
NSArray *array = something;
array = { {1,2}, {2,3}, {3,4} }
that means array is an array of array. so how can you access all the arrays and their values.
we can use for loop like this
for (int i = 0; i < array.count; i++)
{
NSArray x = [array objectAtIndex:i];
}
or a fast enum works like this
for(NSArray array2 in array)
{
// do what ever you want with this new array2.
}
this is a sample example.
PS. I forgot how the array looks in console.