Linux 中使用 Clang 的 Block 扩展

Apr 29, 2023 • 预计阅读时间 1 分钟

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_copyBlock_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

BlocksRuntimecompiler-rt 中的一部分,源码在 https://github.com/llvm/llvm-project/tree/main/compiler-rt/lib/BlocksRuntime

值得一提的是,libblocksruntime-dev 是第三方提供的开源库 BlocksRuntime,使用的源码和 compiler-rt 项目中的是一样的。

clang
版权声明:如果转发请带上本文链接和注明来源。

lvv.me

iOS/macOS Developer

轻量级的时间同步客户端 systemd-timesyncd

使用 OpenSSH 连接到 OpenWRT 的 SSH 服务