Block 是 Objtive-C 语言的一个特性,Clang 把这个特性作为扩展带到了 C/C++ 中: https://clang.llvm.org/docs/BlockLanguageSpec.html
先从 LLVM 的源安装最新版本的 Clang:
sudo apt install lsb-release wget software-properties-common gnupg2
安装 LLVM 源:
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
同时也安装了最新版本的 Clang。
在 Linux 上需要安装 Block 运行库的支持:
sudo apt install libblocksruntime-dev
现在可以在 C/C++ 中使用 Block 特性了:
#include <stdio.h>
int main() {
void (^hello)(void) = ^(void) {
printf("Hello, block!\n");
};
hello();
return 0;
}
如果只是在局部作为匿名函数使用,直接按 Block 的语法书写代码就行,不需要引入额外的头文件。
编译运行:
clang-15 main.c -fblocks -lBlocksRuntime -o test
./test
Block 如果需要传给外部使用,就需要使用 Block_copy
和 Block_release
,这两个函数定义在 Block.h
文件中,
在使用这两个方法之前必须先引入头文件,否则编译会报错。
#include <stdio.h>
#include <Block.h>
typedef void (^block_t)(void);
block_t add(int i) {
return Block_copy(^{
printf("%d + 1 = %d\n", i, i + 1);
});
}
int main() {
block_t block = add(99);
block();
Block_release(block);
return 0;
}
Block_copy
会把 Stack 类型的 Block 变成 Heap 类型,需要和 Block_release
配对使用以防止内存泄露。
Block 也区分逃逸和非逃逸,如果添加了声明 __attribute__((noescape))
,这个变量就是非逃逸的,无法被外部所引用,具体说明参考: https://clang.llvm.org/docs/AttributeReference.html#noescape
BlocksRuntime
是 compiler-rt
中的一部分,源码在 https://github.com/llvm/llvm-project/tree/main/compiler-rt/lib/BlocksRuntime
值得一提的是,libblocksruntime-dev
是第三方提供的开源库 BlocksRuntime,使用的源码和 compiler-rt
项目中的是一样的。