Блоки - это нестандартное расширение, добавленное Apple Inc. к реализациям Clang языков программирования C , C ++ и Objective-C, которые используют синтаксис, подобный лямбда-выражениям, для создания замыканий в этих языках. Блоки поддерживаются для программ, разработанных для Mac OS X 10.6+ и iOS 4.0+, [1] хотя сторонние среды выполнения позволяют использовать их в Mac OS X 10.5 и iOS 2.2+ [2] и в системах сторонних производителей.
Apple разработала блоки с явной целью облегчить написание программ для архитектуры потоковой передачи Grand Central Dispatch [3] [4], хотя она не зависит от этой архитектуры и может использоваться во многом так же, как замыкания в других языках. Apple реализовала блоки как в своей собственной ветви коллекции компиляторов GNU [1], так и во внешнем интерфейсе компилятора Clang LLVM . Поддержка библиотеки языковой среды выполнения для блоков также доступна как часть проекта LLVM. Группа Khronos использует синтаксис блоков для постановки ядер из ядра, начиная с версии 2.0 OpenCL . [5]
Как и определения функций, блоки могут принимать аргументы и внутренне объявлять собственные переменные. В отличие от обычных определений функций C, их значение может захватывать состояние из окружающего их контекста. Определение блока создает непрозрачное значение, которое содержит как ссылку на код внутри блока, так и снимок текущего состояния локальных переменных стека во время его определения. Блок может быть позже вызван таким же образом, как указатель функции. Блок может быть назначен переменным, передан функциям и иным образом обработан как обычный указатель на функцию, хотя прикладной программист (или API) должен пометить блок специальным оператором (Block_copy), если он будет использоваться вне области видимости в который был определен.
Учитывая значение блока, код внутри блока может быть выполнен в любое более позднее время путем его вызова с использованием того же синтаксиса, который использовался бы для вызова функции.
Примеры
Простым примером фиксации изменяемого состояния в окружающей области видимости является итератор целочисленного диапазона : [6]
/ * блоки-test.c * / #include #include / * Тип блока, не принимающего ничего, возвращающего int * / typedef int ( ^ IntBlock ) ();IntBlock MakeCounter ( int start , int increment ) { __block int i = start ;return Block_copy ( ^ ( void ) { int ret = i ; i + = приращение ; return ret ; });}int main ( void ) { IntBlock mycounter = MakeCounter ( 5 , 2 ); printf ( "Первый вызов:% d \ n " , mycounter ()); printf ( "Второй вызов:% d \ n " , mycounter ()); printf ( "Третий вызов:% d \ n " , mycounter ());/ * поскольку он был скопирован, его также необходимо освободить * / Block_release ( mycounter );возврат 0 ; }
Скомпилировать и выполнить
$ clang -fblocks blocks-test.c # Mac OS X $ ./a.out Первый вызов: 5 Второй вызов: 7 Третий вызов: 9
Среда выполнения блоков не является частью библиотеки (библиотек) C, связанных по умолчанию в некоторых системах. В этом случае требуется явная ссылка на эту библиотеку:
$ clang -fblocks blocks-test.c -lBlocksRuntime # Linux
Среда выполнения является частью среды выполнения clang, но иногда не устанавливается вместе с пакетом clang. Доступна автономная среда выполнения, извлеченная из compiler-rt. [7]
Отношение к вложенным функциям GCC
Блоки имеют внешнее сходство с расширением C GCC для поддержки вложенных функций с лексической областью видимости . [8] Однако вложенные функции GCC, в отличие от блоков, не должны вызываться после выхода из содержащей их области, так как это приведет к неопределенному поведению .
Вложенные функции в стиле GCC в настоящее время используют динамическое создание исполняемых преобразователей на большинстве архитектур при получении адреса вложенной функции. На большинстве архитектур (включая X86) эти преобразователи создаются в стеке, что требует пометки исполняемого файла стека. Исполняемые стеки обычно считаются потенциальной дырой в безопасности. Блоки не требуют использования исполняемых преобразователей, поэтому они не разделяют эту слабость. С другой стороны, блоки представляют собой совершенно новый тип указателя, в то время как указатели на вложенные функции в GCC являются обычными указателями на функции и могут использоваться непосредственно с существующим кодом.
Смотрите также
Рекомендации
- ^ a b «Темы программирования блоков» . Разработчик Apple . Apple , Inc . Проверено 8 марта 2011 .
- ^ https://code.google.com/p/plblocks/
- ^ "Grand Central Dispatch" (PDF) (технологический обзор). Apple . 2009-09-03. Архивировано из оригинального (PDF) 20 сентября 2009 года . Проверено 9 июня 2009 года .
- ^ Сиракуза, Джон (1 сентября 2009 г.). «Mac OS X 10.6 Snow Leopard: обзор Ars Technica: блоки» . Ars Technica .
- ^ Мунши, Афтаб, изд. (13.07.2013). «Спецификация OpenCL C. Версия 2.0. Версия документа 11» (PDF) . Рабочая группа Khronos OpenCL. п. 173. Архивировано из оригинального (PDF) 05.11.2013 . Проверено 23 июля 2013 .
- ^ Бенгтссон, Иоахим. «Программирование с помощью C-блоков на устройствах Apple» . Архивировано из оригинала на 2017-11-15 . Проверено 17 сентября 2009 .
- ^ "mackyle / blocksruntime: автономная среда выполнения блоков" . Проверено 15 января 2020 года .
- ^ «Вложенные функции: использование коллекции компиляторов GNU (GCC)» .
Внешние ссылки
- «Расширения языка Clang: блоки» . LLVM Project . Проверено 20 января 2013 .
- " " compiler-rt "Библиотека времени выполнения" . LLVM Project . Проверено 20 января 2013 .