zeroimpl zeroimpl - 2 months ago 6
Objective-C Question

How to convert an array of NSString to an array of c-strings?

I have an

NSArray<NSString*>*
object, and I need to invoke a C API which takes in an array of strings as
char**
.

What's the best way to do this? The important note is the c-strings must not have a
const
modifier, so something like the following isn't good enough since
UTF8String
returns
const char*
:

NSArray<NSString*>* names = ...;
int len = args.count;
char* cNames[len];
for( int i = 0; i < len; i++ ) {
cNames[i] = names[i].UTF8String;
};

Answer

You will want to do some dynamic memory as you cannot rely on the backing memory for UTF8String being released.

NSArray *strings = @[ @"String 1", @"Other string", @"Random String"];
char **cStrings = NULL;
NSInteger numCStrings = strings.count;

if (numCStrings) {
    cStrings = (char **)calloc(numCStrings, sizeof(char*))  ;

    if (cStrings) {
        // Safer to allocate memory for each string

        for (NSInteger i=0;i<numCStrings;i++) {
            NSString *nsString = strings[i];
            char *cString = (char *)malloc(nsString.length + 1);    // + 1 for \0

            if (cString) {
                strcpy(cString, nsString.UTF8String);
                cStrings[i] = cString;
            } else {
                // You should handle your error
            }
        }
    } else {
        // You should handle your error
    }
}

for (NSInteger i=0;i<numCStrings;i++) {
    NSLog(@"C-String (%ld): %s", i, cStrings[i]);
}

// Note you need to free your memory later!
// Do any additional setup after loading the view, typically from a nib.
for (NSInteger i=0;i<numCStrings;i++) {
    if (cStrings[i]) {
        // Free each string
        free(cStrings[i]);
    }
}

// Free the array
free(cStrings);

cStrings = NULL;
numCStrings = 0;