Blocs (extension de langage C) - Blocks (C language extension)

Les blocs sont une extension non standard ajoutée par Apple Inc. aux implémentations de Clang des langages de programmation C , C ++ et Objective-C qui utilise une syntaxe semblable à une expression lambda pour créer des fermetures dans ces langages. Les blocs sont pris en charge pour les programmes développés pour Mac OS X 10.6+ et iOS 4.0+, bien que les environnements d'exécution tiers permettent une utilisation sur les systèmes Mac OS X 10.5 et iOS 2.2+ et non Apple.

Apple a conçu des blocs dans le but explicite de faciliter l'écriture de programmes pour l' architecture de thread de Grand Central Dispatch , bien qu'il soit indépendant de cette architecture et puisse être utilisé à peu près de la même manière que les fermetures dans d'autres langues. Apple a implémenté des blocs à la fois dans sa propre branche de la collection de compilateurs GNU et dans l' interface amont du compilateur Clang LLVM . La prise en charge des bibliothèques d'exécution de langage pour les blocs est également disponible dans le cadre du projet LLVM. Le groupe Khronos utilise la syntaxe des blocs pour mettre les noyaux en file d'attente à partir des noyaux à partir de la version 2.0 d' OpenCL .

Comme les définitions de fonction, les blocs peuvent prendre des arguments et déclarer leurs propres variables en interne. Contrairement aux définitions de fonction C ordinaires, leur valeur peut capturer l'état de leur contexte environnant. Une définition de bloc produit une valeur opaque qui contient à la fois une référence au code dans le bloc et un instantané de l'état actuel des variables de pile locales au moment de sa définition. Le bloc peut être appelé ultérieurement de la même manière qu'un pointeur de fonction. Le bloc peut être affecté à des variables, passé à des fonctions, et autrement traité comme un pointeur de fonction normal, bien que le programmeur d'application (ou l'API) doive marquer le bloc avec un opérateur spécial (Block_copy) s'il doit être utilisé en dehors de la portée de dont il a été défini.

Étant donné une valeur de bloc, le code dans le bloc peut être exécuté ultérieurement en l'appelant, en utilisant la même syntaxe que celle utilisée pour appeler une fonction.

Exemples

Un exemple simple de capture d'un état mutable dans la portée environnante est un itérateur de plage d'entiers :

/* blocks-test.c */
#include <stdio.h>
#include <Block.h>
/* Type of block taking nothing returning an int */
typedef int (^IntBlock)();

IntBlock MakeCounter(int start, int increment) {
	__block int i = start;
	
	return Block_copy( ^(void) {
		int ret = i;
		i += increment;
		return ret;
	});
	
}

int main(void) {
	IntBlock mycounter = MakeCounter(5, 2);
	printf("First call: %d\n", mycounter());
	printf("Second call: %d\n", mycounter());
	printf("Third call: %d\n", mycounter());
	
	/* because it was copied, it must also be released */
	Block_release(mycounter);
	
	return 0;
}

Compiler et exécuter

$ clang -fblocks blocks-test.c # Mac OS X
$ ./a.out
First call: 5
Second call: 7
Third call: 9

Le runtime des blocs ne fait pas partie de la ou des bibliothèques C liées par défaut sur certains systèmes. Si tel est le cas, il est nécessaire de créer un lien explicite vers cette bibliothèque:

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

Le runtime fait partie du runtime de clang, mais n'est parfois pas installé avec le paquet clang. Un runtime autonome extrait de compiler-rt est disponible.

Relation avec les fonctions imbriquées GCC

Les blocs ont une ressemblance superficielle avec l' extension de C de GCC pour prendre en charge les fonctions imbriquées à portée lexicale . Cependant, les fonctions imbriquées de GCC, contrairement aux blocs, ne doivent pas être appelées après la sortie de la portée contenant, car cela entraînerait un comportement indéfini .

Les fonctions imbriquées de style GCC utilisent actuellement la création dynamique de thunks exécutables sur la plupart des architectures en prenant l'adresse de la fonction imbriquée. Sur la plupart des architectures (y compris X86), ces thunks sont créés sur la pile, ce qui nécessite de marquer l'exécutable de la pile. Les piles exécutables sont généralement considérées comme une faille de sécurité potentielle. Les blocs ne nécessitent pas l'utilisation de thunks exécutables, ils ne partagent donc pas cette faiblesse. D'un autre côté, les blocs introduisent un type complètement nouveau pour le pointeur, tandis que les pointeurs vers les fonctions imbriquées dans GCC sont des pointeurs de fonction réguliers et peuvent être utilisés directement avec le code existant.

Voir également

Les références

Liens externes