2009-06-18 19 views
18

podemos convertir NSArray en c array. . Si no lo alternativas existen [supongo que necesito para alimentar la matriz C en funciones de OpenGL, donde la matriz C contiene puntero del vértice leer de archivos plist]NSArray to C array

Respuesta

37

La respuesta depende de la naturaleza de la matriz C.

Si necesita rellenar una matriz de valores primitivos y de longitud conocida, se podría hacer algo como esto:

NSArray* nsArray = [NSArray arrayWithObjects:[NSNumber numberWithInt:1], 
              [NSNumber numberWithInt:2], 
              nil]; 
int cArray[2]; 

// Fill C-array with ints 
int count = [nsArray count]; 

for (int i = 0; i < count; ++i) { 
    cArray[i] = [[nsArray objectAtIndex:i] intValue]; 
} 

// Do stuff with the C-array 
NSLog(@"%d %d", cArray[0], cArray[1]); 

He aquí un ejemplo en el que queremos crear un nuevo C-matriz a partir de una NSArray, manteniendo los elementos de matriz como objetos Obj-C:

NSArray* nsArray = [NSArray arrayWithObjects:@"First", @"Second", nil]; 

// Make a C-array 
int count = [nsArray count]; 
NSString** cArray = malloc(sizeof(NSString*) * count); 

for (int i = 0; i < count; ++i) { 
    cArray[i] = [nsArray objectAtIndex:i]; 
    [cArray[i] retain]; // C-arrays don't automatically retain contents 
} 

// Do stuff with the C-array 
for (int i = 0; i < count; ++i) { 
    NSLog(cArray[i]); 
} 

// Free the C-array's memory 
for (int i = 0; i < count; ++i) { 
    [cArray[i] release]; 
} 
free(cArray); 

O bien, es posible que desee nil termine los de la matriz en lugar de pasar su longitud alrededor:

// Make a nil-terminated C-array 
int count = [nsArray count]; 
NSString** cArray = malloc(sizeof(NSString*) * (count + 1)); 

for (int i = 0; i < count; ++i) { 
    cArray[i] = [nsArray objectAtIndex:i]; 
    [cArray[i] retain]; // C-arrays don't automatically retain contents 
} 

cArray[count] = nil; 

// Do stuff with the C-array 
for (NSString** item = cArray; *item; ++item) { 
    NSLog(*item); 
} 

// Free the C-array's memory 
for (NSString** item = cArray; *item; ++item) { 
    [*item release]; 
} 
free(cArray); 
+2

Esta es una gran respuesta, me gustaría hasta pudiera votar más de una vez. Tengo una sugerencia que es que el uso del tipo 'NSString **' está un poco ofuscado. Sugiero usar '[NSData initWithBytesNoCopy: length: freeWhenDone:]' con el puntero que devuelve malloc y el tamaño de la matriz. – alfwatt

+0

Probé el segundo enfoque que usa malloc, creo que requiere que se desactive el arco. Al menos, así es como lo hice funcionar. Tal vez el arco no existía cuando se formuló esta pregunta ... –

4

que sugeriría para convertir a sí mismo, con algo como:

NSArray * myArray; 

... // code feeding myArray 

id table[ [myArray count] ]; 

int i = 0; 
for (id item in myArray) 
{ 
    table[i++] = item; 
} 
6

NSArray tiene un método -getObjects:range: para crear una matriz C para un subrango de una matriz.

Ejemplo:

NSArray *someArray = /* .... */; 
NSRange copyRange = NSMakeRange(0, [someArray count]); 
id *cArray = malloc(sizeof(id *) * copyRange.length); 

[someArray getObjects:cArray range:copyRange]; 

/* use cArray somewhere */ 

free(cArray); 
+0

Sin embargo, eso no convertirá los objetos NSNumber a un tipo numérico primitivo. El interlocutor necesita esa conversión para usar la matriz C con OpenGL; debido a eso, también podrían poblar por completo la matriz C ellos mismos, sin tener que poner NSNumbers en ella. –

+0

ahhh! No vi el requisito de OpenGL para el problema. En ese caso sí, iterar la matriz manualmente sería apropiado. –