stringtranslate.com

Bloques (extensión del lenguaje C)

Los bloques son una extensión no estándar agregada por Apple Inc. a las implementaciones de Clang de los lenguajes de programación C , C++ y Objective-C que utiliza una sintaxis similar a una expresión lambda para crear cierres dentro de estos lenguajes. Los bloques son compatibles con programas desarrollados para Mac OS X 10.6+ y iOS 4.0+, [1] aunque los entornos de ejecución de terceros permiten su uso en Mac OS X 10.5 e iOS 2.2+ [2] y sistemas que no sean de Apple.

Apple diseñó bloques con el objetivo explícito de facilitar la escritura de programas para la arquitectura de subprocesamiento Grand Central Dispatch , [3] [4] aunque es independiente de esa arquitectura y se puede utilizar de la misma manera que los cierres en otros lenguajes. Apple ha implementado bloques tanto en su propia rama de la Colección de compiladores GNU [1] como en el frontend del compilador Clang LLVM . El soporte de la biblioteca de ejecución de lenguaje para bloques también está disponible como parte del proyecto LLVM. El grupo Khronos utiliza la sintaxis de bloques para poner en cola los núcleos desde dentro de los núcleos a partir de la versión 2.0 de OpenCL . [5]

Al igual que las definiciones de funciones, los bloques pueden tomar argumentos y declarar sus propias variables internamente. A diferencia de las definiciones de funciones de C ordinarias, su valor puede capturar el estado de su contexto circundante. Una definición de bloque produce un valor opaco que contiene tanto una referencia al código dentro del bloque como una instantánea del estado actual de las variables de la pila local en el momento de su definición. El bloque puede invocarse posteriormente de la misma manera que un puntero de función. El bloque puede asignarse a variables, pasarse a funciones y tratarse de otro modo como un puntero de función normal, aunque el programador de la aplicación (o la API) debe marcar el bloque con un operador especial (Block_copy) si se va a utilizar fuera del ámbito en el que se definió.

Dado un valor de bloque, el código dentro del bloque se puede ejecutar en cualquier momento posterior llamándolo, utilizando la misma sintaxis que se usaría para llamar a una función.

Ejemplos

Un ejemplo simple que captura el estado mutable en el ámbito circundante es un iterador de rango entero : [6]

/* blocks-test.c */ #include <stdio.h> #include <Block.h> /* Tipo de bloque que no toma nada que devuelva un int */ typedef int ( ^ IntBlock )();    IntBlock MakeCounter ( int inicio , int incremento ) { __block int i = inicio ; return Block_copy ( ^ ( void ) { int ret = i ; i += incremento ; return ret ; }); }                  int main ( void ) { IntBlock mycounter = MakeCounter ( 5,2 ) ; printf ( "Primera llamada: %d \n " , mycounter ()); printf ( " Segunda llamada: %d \n " , mycounter ()); printf ( "Tercera llamada: %d \n " , mycounter ()); /* debido a que fue copiado, también debe ser liberado */ Block_release ( mycounter ); return 0 ; }          

Compilar y ejecutar

$ clang  -fblocks  blocks-test.c # Mac OS X $ ./a.out Primera llamada: 5 Segunda llamada: 7 Tercera llamada: 9 

El entorno de ejecución de bloques no forma parte de las bibliotecas C vinculadas de forma predeterminada en algunos sistemas. Si este es el caso, es necesario vincularlo explícitamente a esta biblioteca:

$ clang  -fblocks  bloques-test.c  -lBlocksRuntime # Linux 

El entorno de ejecución es parte del entorno de ejecución de clang, pero a veces no se instala con el paquete clang. Hay disponible un entorno de ejecución independiente extraído de compiler-rt. [7]

Relación con las funciones anidadas de GCC

Los bloques tienen un parecido superficial con la extensión de C de GCC para soportar funciones anidadas con alcance léxico . [8] Sin embargo, las funciones anidadas de GCC, a diferencia de los bloques, no deben llamarse después de que el alcance que las contiene haya salido, ya que eso daría como resultado un comportamiento indefinido .

Las funciones anidadas de estilo GCC actualmente utilizan la creación dinámica de thunks ejecutables en la mayoría de las arquitecturas al tomar la dirección de la función anidada. En la mayoría de las arquitecturas (incluida X86), estos thunks se crean en la pila, lo que requiere marcar la pila como ejecutable. Las pilas ejecutables generalmente se consideran un potencial agujero de seguridad. Los bloques no requieren el uso de thunks ejecutables, por lo que no comparten esta debilidad. Por otro lado, los bloques introducen un tipo completamente nuevo para el puntero, mientras que los punteros a funciones anidadas en GCC son punteros de función regulares y se pueden usar directamente con el código existente.

Véase también

Referencias

  1. ^ ab "Temas de programación de bloques". Apple Developer . Apple Inc . Consultado el 8 de marzo de 2011 .
  2. ^ "Archivo de código de Google: almacenamiento a largo plazo para alojamiento de proyectos de código de Google".
  3. ^ "Grand Central Dispatch" (PDF) (informe tecnológico). Apple . 3 de septiembre de 2009. Archivado desde el original (PDF) el 20 de septiembre de 2009. Consultado el 9 de junio de 2009 .
  4. ^ Siracusa, John (1 de septiembre de 2009). "Mac OS X 10.6 Snow Leopard: la reseña de Ars Technica: Blocks". Ars Technica .
  5. ^ Munshi, Aaftab, ed. (13 de julio de 2013). "La especificación C de OpenCL. Versión 2.0. Revisión del documento 11" (PDF) . Khronos OpenCL Working Group. pág. 173. Archivado desde el original (PDF) el 5 de noviembre de 2013. Consultado el 23 de julio de 2013 .
  6. ^ Bengtsson, Joachim. "Programación con bloques C en dispositivos Apple". Archivado desde el original el 15 de noviembre de 2017. Consultado el 17 de septiembre de 2009 .
  7. ^ "mackyle/blocksruntime: tiempo de ejecución de bloques independiente" . Consultado el 15 de enero de 2020 .
  8. ^ "Funciones anidadas: uso de la colección de compiladores GNU (GCC)".

Enlaces externos