Search code examples
ccore-foundation

Wrap C primitive values in CFArray of CFNumbers


What is the best way to implement a method to wrap a C array of primitive numbers into a CFArray of CFNumbers?

I want to call something like:

double values[] = {1.2345, 678.9};
CFArrayRef arr = NumberWrappedValuesArray(&values, 2, kCFNumberDoubleType);

And tried this:

CFArrayRef NumberWrappedValuesArray(void * valueArrayPtr, CFIndex count, CFNumberType numberType) {
    CFMutableArrayRef array = CFArrayCreateMutable(NULL, count, &kCFTypeArrayCallBacks);

    for (int i = 0; i < count; i++) {
        CFNumberRef numberWrappedValue = CFNumberCreate(NULL, numberType, &valueArrayPtr[i]);
        CFArrayAppendValue(array, numberWrappedValue);
        CFRelease(numberWrappedValue);
    }

    CFRelease(array);
    return array;
}
  1. It doesn't work (returned array has 0 elements), why and how do I fix it?
  2. Is there a more elegant way, potentially avoiding the mutable CFArray?

Thanks!


Solution

  • You can use CFArrayCreate.

    Example:

    CFArrayRef NumberWrappedValuesArray(void *valueArrayPtr, size_t size, CFIndex count, CFNumberType numberType) {
        size_t i, n;
        CFArrayRef ret;
        CFNumberRef *ref = malloc(sizeof(CFNumberRef) * count);
    
        /* create array of boxed types. */
        for (i = 0, n = count; i < n; ++i)
            ref[i] = CFNumberCreate(NULL, numberType, ((char *)valueArrayPtr) + (size * i));
    
        /* create CFArray. */
        ret = CFArrayCreate(NULL, (const void **)ref, count, &kCFTypeArrayCallBacks);
    
        /* release boxed types and malloc'ed array. */
        for (i = 0; i < n; ++i)
            CFRelease(ref[i]);
        free(ref);
    
        /* return CFArray, without releasing first! Has to be done by the caller. */
        return ret;
    }
    

    Error handling omitted for clarity.