Mercurial
annotate mrjunejune/src/blog/wasm-bunny/index.md @ 169:295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 19 Jan 2026 17:33:18 -0800 |
| parents | 65e5a5b89a4e |
| children | 8c74204fd362 |
| rev | line source |
|---|---|
|
169
295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
MrJuneJune <me@mrjunejune.com>
parents:
100
diff
changeset
|
1 --- |
|
295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
MrJuneJune <me@mrjunejune.com>
parents:
100
diff
changeset
|
2 title: First Steps with C3 and Raylib on WebAssembly |
|
295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
MrJuneJune <me@mrjunejune.com>
parents:
100
diff
changeset
|
3 description: Experimenting with C3 programming language and Raylib to build an interactive bunnymark benchmark compiled to WebAssembly. |
|
295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
MrJuneJune <me@mrjunejune.com>
parents:
100
diff
changeset
|
4 --- |
|
295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
MrJuneJune <me@mrjunejune.com>
parents:
100
diff
changeset
|
5 |
|
100
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
6 # First Steps with C3 and Raylib on WebAssembly |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
7 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
8 Hi! This is my first blog post on this website, and hopefully, it’s the first of many, as I have some free time at the moment. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
9 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
10 Today, I spent a few hours experimenting with the programming language [C3](https://c3-lang.org/) and linking it with a static file from [Raylib](https://www.raylib.com/), a popular library for creating web applications. My goal was to build something interactive and deploy it to the web with minimal hassle. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
11 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
12 I’ve set up a repository to link C3 with Raylib and stress-test it using a bunny-rendering benchmark, inspired by this [bunnymark benchmark](https://old.reddit.com/r/raylib/comments/15jy1x3/raylib_bunnymark_benchmark_with_100k_bunnies/). |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
13 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
14 Here are some key things to keep in mind when compiling C3 and Raylib to WebAssembly (WASM): |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
15 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
16 ## Limited WASM Support in C3: |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
17 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
18 C3 has limited support for compiling to [WASM](https://c3-lang.org/faq/#platform-support). The standard library isn't usable in WASM, so any standard functions need to be rewritten or excluded. For example, I attempted to randomly assign colors to a rabbit, but there was no compile-time error, so I had to debug why WASM wasn’t loading properly. In hindsight, I should have known, given that the `--link-libc=no` flag was used in the examples. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
19 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
20 Example command: |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
21 ``` |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
22 c3c compile --reloc=none --target wasm32 -g0 --link-libc=no --no-entry main.c3 raylib.c3 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
23 ``` |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
24 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
25 ## Custom Raylib JavaScript File: |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
26 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
27 Raylib APIs need to be called through a custom `raylib.js` file. As shown in the command above, there’s no static Raylib file (`raylib.a`) linked directly to WASM. Instead, Raylib APIs are accessed through JavaScript using [WebAssembly.instantiateStreaming](https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/instantiateStreaming_static). For example, `raylib::init_window` would be called in JavaScript like this: |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
28 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
29 ```javascript |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
30 function InitWindow(width, height, title_ptr) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
31 this.ctx.canvas.width = width; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
32 this.ctx.canvas.height = height; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
33 const buffer = this.wasm.instance.exports.memory.buffer; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
34 document.title = cstr_by_ptr(buffer, title_ptr); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
35 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
36 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
37 const raylibObject = { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
38 raylib: { InitWindow: InitWindow }, |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
39 }; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
40 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
41 WebAssembly.instantiateStreaming(fetch("main.wasm"), raylibObject).then( |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
42 (obj) => obj.instance.exports.exported_func(), |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
43 ); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
44 ``` |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
45 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
46 To actaully link it together, I was lucky to find raylib.js [this repo](https://github.com/tsoding/c3-demo/blob/main/raylib.js) (Thanks tsoding!!). I only needed to add a few functions for handling clicks. The file had `RaylibJs` class which need to be turned into object from above example and used `Proxy` class to do that. I actaully never seen that API being used outside of this. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
47 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
48 ```javascript |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
49 function make_environment(env) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
50 return new Proxy(env, { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
51 get(_target, prop, _receiver) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
52 if (env[prop] !== undefined) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
53 return env[prop].bind(env); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
54 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
55 return (...args) => { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
56 throw new Error(`NOT IMPLEMENTED: ${prop} ${args}`); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
57 }; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
58 }, |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
59 }); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
60 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
61 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
62 class RaylibJs { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
63 // will have all raylib functions |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
64 ... |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
65 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
66 IsMouseButtonPressed(key) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
67 return this.currentIsMouseButtonPressed == key; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
68 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
69 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
70 // entrypoints to fetch wasm and start it. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
71 start(wasmPath, canvasId) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
72 ... |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
73 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
74 this.wasm = await WebAssembly.instantiateStreaming(fetch(wasmPath), { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
75 env: make_environment(this), |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
76 }); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
77 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
78 // Call the main functions from wasm object |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
79 this.wasm.instance.exports.main(); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
80 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
81 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
82 ``` |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
83 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
84 Overall, this was an interesting project to spend a few hours on, and maybe in the future, I’ll explore compiling the C3 standard library to WASM. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
85 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
86 Below are the results! |