2012-06-28 13 views
7

Ho un gioco multipiattaforma scritto in C++. Nella versione mac, anche se non ho alcun codice obj-c, una delle librerie che uso sembra essere auto-releasing, e ottengo perdite di memoria per questo, dal momento che non ho creato un NSAutoreleasePool.Come creare un NSAutoreleasePool senza Objective-C?

Quello che voglio è essere in grado di creare (e distruggere) un NSAutoreleasePool senza usare il codice obj-c, quindi non ho bisogno di creare un file .m, e cambiare i miei script di compilazione solo per quello. È possibile? Come può essere fatto?

OBS: Tagged C e C++, perché una soluzione in ognuna di queste lingue lo farà.

+0

Il tuo problema sta scrivendo un codice obiettivo-c? O avendo i file .m nel tuo progetto quando vuoi solo .c/.cpp? – Sean

+1

Si noti che mentre il codice di @ abarnert è una soluzione praticabile, questo indica un bug nella libreria. Nessuna funzione C o C++ deve chiamare nel codice ObjC senza generare un pool autorelease. Se questo è il codice Apple, dovresti aprire un radar su bugreport.apple.com. –

+0

@Sean Desidero solo file .c/.cpp. So che posso escludere quei file sull'altra piattaforma, ma sto cercando di evitarlo. – fbafelipe

risposta

2

Non è possibile evitare di creare un'istanza del runtime Objective-C, ma a quanto pare ne hai già uno.

Se si desidera interagire con il runtime da C, è possibile utilizzare le API runtime Objective-C, come documentato in Objective-C Runtime Programming Guide e Objective-C Runtime Reference.

L'idea è qualcosa di simile (non testata):

#include <objc/runtime.h> 
#include <objc/objc-runtime.h> 
id allocAndInitAutoreleasePool() { 
    Class NSAutoreleasePoolClass = objc_getClass("NSAutoreleasePool"); 
    id pool = class_createInstance(NSAutoreleasePoolClass, 0); 
    return objc_msgSend(pool, "init"); 
} 
void drainAutoreleasePool(id pool) { 
    (void)objc_msgSend(pool, "drain"); 
} 

Se si desidera chiamare queste funzioni da un altro file, ovviamente dovrete includere objc/runtime.h anche lì. Oppure, in alternativa, puoi lanciare l'id per annullare * nel ritorno dalla funzione allocAndInit, e prendere un void * e ricondurlo all'id nella funzione drain. (Si potrebbe anche inoltrare -dire struct objc_object e typedef struct objc_object * id, ma credo che non sia in realtà garantito la definizione corretta.)

Non si dovrebbe passare a -lobjc nel comando di collegamento.

Inutile dire che probabilmente è meno lavoro solo per fare in modo che gli script di compilazione gestiscano i file .m.

+2

Dovresti riuscire a caricare i file di runtime con puro codice C (senza richiedere '-lobjc'). Puoi vedere un esempio di questo qui: https://github.com/rnapier/ios5ptl/blob/master/ch20/Runtime/MyMsgSend.c (non ti sto raccomandando di usare 'myMsgSend()', è una dimostrazione di qualcos'altro, sto solo mostrando un file C compilabile che mostra che questo approccio funziona.) –

+1

Come nota a margine, mentre i file '.m' potrebbero essere ok, non è consigliabile aggirare questo problema con'. file mm' tranne che in involucri molto piccoli. ObjC++ causa molti problemi. Va bene come un piccolo pezzo di colla, e questo è un ottimo modo per risolvere questo problema (attaccare la chiamata in una piccola funzione '.mm' con un header C o C++ puro e un @autorelease {} attorno alla chiamata). Ma mantieni puro il tuo C++ e il tuo ObjC. –

+0

@RobNapier: grazie per la nota su -lobjc. Aggiornerò la risposta – abarnert

Problemi correlati