resueltos - funcion si con dos condiciones
¿Reescribe la macro de limpieza de GCC con la función anidada para Clang? (1)
Clang no es compatible con las funciones anidadas de GCC, pero sí admite los "bloques" de estilo Objective C , incluso en el modo C:
void f(void * d) {
void (^g)(void *) = ^(void * d){ };
g(d);
}
-fblocks -lBlocksRuntime
invocarlo con el comando clang
lugar de gcc
, y también (?) Pasar -fblocks -lBlocksRuntime
al compilador.
No puede usar un bloque directamente como un valor de cleanup
, ya que tiene que ser un nombre de función, por lo que (al robar ideas de aquí ) debe agregar una capa de indirección. Defina una función única para limpiar los bloques vacíos y convierta su variable RAII en el bloque que desea ejecutar al final del alcance:
typedef void (^cleanup_block)(void);
static inline void do_cleanup(cleanup_block * b) { (*b)(); }
void do_stuff(const char *name) {
cleanup_block __attribute__((cleanup(do_cleanup))) __b = ^{ };
}
Como los bloques forman cierres, puede colocar las operaciones en sus variables para limpiarlas directamente dentro de ese bloque ...
void do_stuff(const char *name) {
struct mything * thing;
cleanup_block __attribute__((cleanup(do_cleanup))) __b = ^{ ao2_cleanup(thing); };
}
... y eso debería ejecutarse al final del alcance como antes, invocado por la limpieza en el bloque. Reorganiza la macro y agrega un __LINE__
para que funcione con múltiples declaraciones:
#define CAT(A, B) CAT_(A, B)
#define CAT_(A, B) A##B
#define RAII_VAR(vartype, varname, initval, dtor) /
vartype varname = (initval); /
cleanup_block __attribute__((cleanup(do_cleanup))) CAT(__b_, __LINE__) = ^{ dtor(varname); };
void do_stuff(const char *name) {
RAII_VAR(struct mything *, thing, NULL, ao2_cleanup);
...
Algo así, de todos modos.
Estoy tratando de resolver un problema en una biblioteca de terceros. El problema es que la biblioteca utiliza las funciones anidadas de GCC enterradas en una macro, y Clang no admite funciones anidadas y no tiene planes de hacerlo (cf., Clang Bug 6378 - error: clase de almacenamiento ilegal en la función ).
Aquí está la macro, ese es el punto de dolor para mí y Clang:
#define RAII_VAR(vartype, varname, initval, dtor) /
/* Prototype needed due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36774 */ /
auto void _dtor_ ## varname (vartype * v); /
void _dtor_ ## varname (vartype * v) { dtor(*v); } /
vartype varname __attribute__((cleanup(_dtor_ ## varname))) = (initval)
Y así es como se usa (a partir de los comentarios del código):
* void do_stuff(const char *name)
* {
* RAII_VAR(struct mything *, thing, find_mything(name), ao2_cleanup);
* if (!thing) {
* return;
* }
* if (error) {
* return;
* }
* do_stuff_with_thing(thing);
* }
La Manua de usuario de Clang indica que debe usar C ++ y una función lambda para emular. No estoy seguro de que esa sea la mejor estrategia, y un proyecto de C probablemente no acepte un parche de C ++ (probablemente, primero me asaltarían y escribirían).
¿Hay alguna manera de reescribir la macro para que sea (1) más complaciente con Clang y (2) preserve la semántica de la función original?