2012-01-06 5 views
6

Dato che ho un identificatore di tipo restituito da method_copyReturnType(). Nel runtime GNU fornito con GCC ci sono vari metodi per lavorare con un identificatore di tipo come objc_sizeof_type(), objc_alignof_type() e altri.Come interpretare l'identificatore del tipo ogg-c (ad esempio, restituito da method_copyReturnType())?

Quando si utilizza il runtime di Apple, non esistono tali metodi.

Come interpretare una stringa identificatore di tipo (ad esempio ottenere la dimensione di un tipo) utilizzando il runtime Apple senza implementando un se/else o l'interruttore di caso per me stesso?

[update]

io non sono in grado di utilizzare la Fondazione Apple.

risposta

2

afaik, dovrai inserire le informazioni nel tuo file binario. basta creare una funzione che restituisce la dimensione e l'allineamento in una struttura, supporta i tipi che è necessario supportare, quindi chiama tale funzione (o metodo di classe) per le informazioni.

Il programma seguente mostra che molti dei primitivi sono solo un carattere. Quindi la maggior parte dell'implementazione della funzione potrebbe essere un cambiamento.

static void test(SEL sel) { 
    Method method = class_getInstanceMethod([NSString class], sel); 

    const char* const type = method_copyReturnType(method); 

    printf("%s : %s\n", NSStringFromSelector(sel).UTF8String, type); 

    free((void*)type); 
} 

int main(int argc, char *argv[]) { 
    @autoreleasepool { 

     test(@selector(init)); 
     test(@selector(superclass)); 
     test(@selector(isEqual:)); 
     test(@selector(length)); 

     return 0; 
    } 
} 

e si potrebbe quindi utilizzare questo come punto di partenza:

typedef struct t_pair_alignof_sizeof { 
    size_t align; 
    size_t size; 
} t_pair_alignof_sizeof; 

static t_pair_alignof_sizeof MakeAlignOfSizeOf(size_t align, size_t size) { 
    t_pair_alignof_sizeof ret = {align, size}; 
    return ret; 
} 

static t_pair_alignof_sizeof test2(SEL sel) { 
    Method method = class_getInstanceMethod([NSString class], sel); 
    const char* const type = method_copyReturnType(method); 
    const size_t length = strlen(type); 

    if (1U == length) { 
     switch (type[0]) { 
      case '@' : 
       return MakeAlignOfSizeOf(__alignof__(id), sizeof(id)); 
      case '#' : 
       return MakeAlignOfSizeOf(__alignof__(Class), sizeof(Class)); 
      case 'c' : 
       return MakeAlignOfSizeOf(__alignof__(signed char), sizeof(signed char)); 
      ... 
+0

Quindi la risposta è: non c'è modo di farlo senza implementarlo da solo. Corretta? –

+0

@Tilo Ho fatto alcune cose stupide con il runtime - non c'è alcuna soluzione gratuita che io conosca, ma la soluzione nella mia risposta può essere implementata abbastanza facilmente se si conoscono i tipi che si devono supportare. Certo, puoi anche aspettare e vedere se ottieni una risposta più appropriata. – justin

+0

@Tilo - aggiunta una demo per questo – justin

5

Credo che stai cercando NSGetSizeAndAlignment:

ottiene la dimensione reale e la dimensione allineata di un tipo codificato.

const char * NSGetSizeAndAlignment (
    const char *typePtr, 
    NSUInteger *sizep, 
    NSUInteger *alignp 
);

Discussione
Ottiene la dimensione effettiva e la dimensione allineata del primo tipo di dati rappresentata dai typePtr e restituisce un puntatore alla posizione del successivo tipo di dati in typePtr.

Questa è una funzione Foundation, non parte del runtime di base, che è probabilmente il motivo per cui non è stata trovata.

UPDATE: Anche se inizialmente non menziona che si sta utilizzando Cocotron, è disponibile anche lì. Puoi trovarlo in Cocotron's Foundation, nello NSObjCRuntime.m.

Ovviamente, questo è molto meglio del proprio, poiché si può essere sicuri che gestisca sempre correttamente le stringhe generate dal proprio runtime nell'improbabile eventualità che i caratteri di codifica cambino.

Per qualche motivo, tuttavia, non è in grado di gestire gli elementi di una stringa di firma del metodo (che presumibilmente hanno qualcosa a che fare con gli offset in memoria).-400-lo farà:

static const char *SizeAndAlignment(const char *str, NSUInteger *sizep, NSUInteger *alignp, int *len) 
{ 
    const char *out = NSGetSizeAndAlignment(str, sizep, alignp); 
    if(len) 
     *len = out - str; 
    while(isdigit(*out)) 
     out++; 
    return out; 
} 
+0

+1 buona ricerca, Josh – justin

+0

Il problema è che non ho un accesso generale a Apple Foundation poiché esiste solo per i prodotti Apple :). Il progetto a cui sto lavorando è Cocotron (un'alternativa alla Fondazione). Quindi non posso usare i metodi della Fondazione. –

+0

@Tilo: il framework che stai utilizzando è una ** condizione piuttosto grande ** che probabilmente avresti dovuto includere nella domanda per iniziare. La stessa funzione è, tuttavia, disponibile in Cococtron. Vedi la mia modifica. –

Problemi correlati