Skip to content

Instantly share code, notes, and snippets.

@ziap
Last active September 16, 2023 03:59
Show Gist options
  • Save ziap/64d20abbe51e1f16ee2465d0c6257324 to your computer and use it in GitHub Desktop.
Save ziap/64d20abbe51e1f16ee2465d0c6257324 to your computer and use it in GitHub Desktop.
printf for WASM. Requires std_sprintf <https://github.com/nothings/stb>
#ifndef JS_PRINTF_H
#define JS_PRINTF_H
// This is free and unencumbered software released into the public domain.
// Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
// software, either in source code form or as a compiled binary, for any purpose,
// commercial or non-commercial, and by any means.
// In jurisdictions that recognize copyright laws, the author or authors of this
// software dedicate any and all copyright interest in the software to the public
// domain. We make this dedication for the benefit of the public at large and to
// the detriment of our heirs and successors. We intend this dedication to be an
// overt act of relinquishment in perpetuity of all present and future rights to
// this software under copyright law.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Example usage:
// file: hello.c
// #define export __attribute__((visibility("default")))
//
// #define JS_PRINTF_IMPLEMENTATION
// #include "js_printf.h"
//
// export void hello(int a, int b) {
// js_printf("Hello, %s!\n", "world");
// js_printf("%d + %d = %d\n", a, b, a + b);
// }
// file: hello.js
// let memory_buffer
// const decoder = new TextDecoder()
//
// let buf = ""
//
// const wasm = await WebAssembly.instantiateStreaming(fetch("./hello.wasm"), {
// env: {
// js_append_buf(ptr, len) {
// const bytes = new Uint8Array(memory_buffer, ptr, len)
// buf += decoder.decode(bytes)
// },
// js_flush_buf() {
// console.log(buf)
// buf = ""
// }
// }
// })
//
// const { exports } = wasm.instance
//
// memory_buffer = exports.memory.buffer
//
// exports.hello(34, 35)
// Compile with: clang -o hello.wasm hello.c -O3 -Wall -Wextra -Wpedantic
// -std=c99 -O3 --target=wasm32 -flto -nostdlib -fvisibility=hidden
// -mbulk-memory -msimd128 -Wl,--no-entry -Wl,--strip-debug -Wl,--lto-O3
// -Wl,--allow-undefined -Wl,--export-dynamic
extern void js_printf(const char* fmt, ...);
#endif
#ifdef JS_PRINTF_IMPLEMENTATION
#define STB_SPRINTF_IMPLEMENTATION
#include "stb_sprintf.h"
extern void js_append_buf(const char*, int);
extern void js_flush_buf(void);
char* js_printf_cb(const char* buf, void* user, int len) {
stbsp__context *c = (stbsp__context *)user;
js_append_buf(buf, len);
return c->tmp;
}
void js_printf(const char* fmt, ...) {
stbsp__context c;
va_list va;
va_start(va, fmt);
stbsp_vsprintfcb(js_printf_cb, &c, c.tmp, fmt, va);
va_end(va);
js_flush_buf();
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment