2012-06-28 18 views
7

Tengo un juego multiplataforma escrito en C++. En la versión mac, aunque no tengo ningún código obj-c, una de las bibliotecas que uso parece estar liberando automáticamente cosas, y tengo pérdidas de memoria por eso, ya que no creé un NSAutoreleasePool.¿Cómo crear un NSAutoreleasePool sin Objective-C?

Lo que quiero es poder crear (y destruir) un NSAutoreleasePool sin usar el código obj-c, así que no necesito crear un archivo .m y cambiar mis scripts de compilación solo por eso. ¿Es eso posible? ¿Cómo se puede hacer eso?

OBS: Etiquetado C y C++, porque una solución en cualquiera de esos idiomas servirá.

+0

¿Su problema es escribir algún código object-c en absoluto? ¿O tener archivos .m en su proyecto cuando solo quiere .c/.cpp? – Sean

+1

Tenga en cuenta que si bien el código de @ abarnert es una solución viable, esto indica un error en la biblioteca. Ninguna función C o C++ debe llamar al código ObjC sin generar un grupo de autorrelease. Si este es el código de Apple, deberías abrir un radar en bugreport.apple.com. –

+0

@Sean Solo quiero archivos .c/.cpp. Sé que puedo excluir esos archivos para la construcción de otras plataformas, pero estoy tratando de evitar eso. – fbafelipe

Respuesta

2

No puede evitar crear instancias del tiempo de ejecución de Objective-C, pero aparentemente ya tiene una de esas.

Si desea interactuar con el tiempo de ejecución de C, puede usar las API de tiempo de ejecución de Objective-C, como se documenta en Objective-C Runtime Programming Guide y Objective-C Runtime Reference.

La idea es algo como esto (no probado):

#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"); 
} 

Si desea llamar a estas funciones desde otro archivo, por supuesto, usted tiene que incluir objc/runtime.h allí también. O bien, alternativamente, puede convertir el id a void * en el retorno de la función allocAndInit, y tomar un vacío * y devolverlo a id en la función de drenaje. (También podría reenviar-declarar struct objc_object y typedef struct objc_object * id, pero creo que no está garantizado que sea la definición correcta).

No debería tener que pasar -lobjc en su comando de enlace.

Huelga decir que, probablemente sea menos trabajo hacer que sus scripts de construcción manejen archivos .m.

+2

Debería poder cargar los archivos de tiempo de ejecución con código C puro (sin requerir '-lobjc'). Puede ver un ejemplo de esto aquí: https://github.com/rnapier/ios5ptl/blob/master/ch20/Runtime/MyMsgSend.c (No estoy recomendando que use 'myMsgSend()', es una demostración de otra cosa. Solo estoy mostrando un archivo C compilable que muestra que este enfoque funciona.) –

+1

Como nota al margen, mientras que los archivos '.m' podrían estar bien, no recomiendo que solucione este problema con'. archivos mm' excepto como envoltorios muy pequeños. ObjC++ causa muchos problemas. Está bien como un pequeño trozo de pegamento, y esa es una buena forma de resolver este problema (pegue la llamada en una pequeña función '.mm' con un encabezado C o C++ puro y un @autorelease {} alrededor de la llamada). Pero mantén tu C++ puro y tu ObjC puro. –

+0

@RobNapier: Gracias por la nota en -lobjc. Actualizaré la respuesta. – abarnert

Cuestiones relacionadas