0%

embed in C23

其實這也不是什麼新玩意,不過由於AI和其他方面的需求加持,這東西越來越重要
先分析一下問題

Problem

假設我們想在程式裡面直接嵌入icon或是wave,該怎麼做

1
uint8_t icon[];

現在的問題,嵌入的content是Binary的,如何跟程式綁在一起

Solution 1: String Literal

使用類似xxd, objcopy或是類似的工具,將Binary轉成String Literal,然後跟原先的程式做聯結就行了
不過可能遇到的問題

  • xxd 或是其他的工具,該作業系統可能不能用或是要額外安裝,增加額外的複雜性
  • 增加編譯的複雜度,必須先處理String literal,才能編譯相依的程式碼

Solution 2: Linker

直接從Linker動手腳

1
$ ld -r -b binary -o binary.o foo.bar  # then link in binary.o
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

extern char _binary_foo_bar_start[];
extern char _binary_foo_bar_end[];

int main(void)
{
printf( "address of start: %p\n", &_binary_foo_bar_start);
printf( "address of end: %p\n", &_binary_foo_bar_end);

for (char* p = _binary_foo_bar_start; p != _binary_foo_bar_end; ++p) {
putchar( *p);
}

return 0;
}

這遇到的問題跟上面差不多

唯一解決的問題是跨平台,複雜度還是無法解決
有沒有更簡單的方法

golang

看看golang的例子,簡單明瞭

1
2
3
4
5
6
import (
_ "embed"
)

//go:embed hello.txt
var s string

embed in C23

終於講到主題了,在C23中可以這麼做

1
2
3
4
5
6
7
8
9
10
11
#include <stddef.h>

void show_icon(const unsigned char *, size_t);

int main (int, char*[]) {
static const unsigned char icon_data[] = {
#embed "black_sheep.ico"
};
show_icon(icon_data, sizeof(icon_data));
return 0;
}

這解決了編譯相依性的問題,不過沒有實質性的改進,C++目前沒有對應的東西
如果你以前的方式跑得好好的,不會因為編譯速度還煩惱的話,沒有必要一定要使用

Reference