From 01daac07b08d5313325d4e48777c2c4257980092 Mon Sep 17 00:00:00 2001 From: Anthony Date: Thu, 20 Jun 2024 16:18:49 -0500 Subject: [PATCH] add build (code) artifacts to main --- azure/docsite/api/api-c-con/index.html | 2 +- azure/docsite/api/api-c-d2d/index.html | 2 +- azure/docsite/api/api-c-general/index.html | 3 +- azure/docsite/api/api-libc++/index.html | 37 ++++++------- .../gettingstarted/compiler-opts/index.html | 16 +++--- azure/docsite/index.html | 18 +++--- azure/docsite/more/debugging/index.html | 10 ++-- azure/docsite/search/search_index.json | 2 +- azure/docsite/sitemap.xml | 52 +++++++++--------- azure/docsite/sitemap.xml.gz | Bin 426 -> 425 bytes azure/examples/balls/balls-a.wasm | Bin 36194 -> 36226 bytes azure/examples/balls/balls-dbg.wasm | Bin 251523 -> 253283 bytes azure/examples/balls/balls.wasm | Bin 36050 -> 36082 bytes azure/examples/dist/balls/balls-a.wasm | Bin 36194 -> 36226 bytes azure/examples/dist/balls/balls-dbg.wasm | Bin 251523 -> 253283 bytes azure/examples/dist/balls/balls.wasm | Bin 36050 -> 36082 bytes azure/examples/dist/balls/index.html | 2 +- azure/examples/dist/fft/index.html | 2 +- azure/examples/dist/fft/kiss_fft.wasm | Bin 24738 -> 24770 bytes azure/examples/dist/function-calls/async.html | 2 +- .../dist/function-calls/function-calls-a.wasm | Bin 200456 -> 202235 bytes .../dist/function-calls/function-calls.wasm | Bin 200318 -> 202097 bytes azure/examples/dist/function-calls/index.html | 2 +- .../examples/dist/helloworld/helloworld.wasm | Bin 21633 -> 21665 bytes azure/examples/dist/helloworld/index.html | 2 +- azure/examples/dist/lib-js.30177026.js | 2 - azure/examples/dist/lib-js.30177026.js.map | 1 - azure/examples/dist/lib-js.433b837a.js | 2 + azure/examples/dist/lib-js.433b837a.js.map | 1 + azure/examples/dist/maze/index.html | 2 +- azure/examples/dist/maze/maze.wasm | Bin 33472 -> 33504 bytes azure/examples/dist/stdio-canvas/index.html | 2 +- .../dist/stdio-canvas/stdio-canvas.wasm | Bin 27729 -> 27753 bytes azure/examples/dist/stdio-div/index.html | 2 +- azure/examples/dist/stdio-div/stdio-div.wasm | Bin 28655 -> 28693 bytes azure/examples/dist/tests-libcxx/index.html | 2 +- .../dist/tests-libcxx/tests-libcxx.wasm | Bin 278815 -> 294102 bytes azure/examples/dist/tests-user/index.html | 2 +- .../examples/dist/tests-user/tests-user.wasm | Bin 1213573 -> 1225510 bytes azure/examples/dist/tests/index.html | 2 +- azure/examples/dist/tests/tests-dbg.wasm | Bin 289978 -> 293881 bytes azure/examples/dist/tests/tests.wasm | Bin 67188 -> 67738 bytes azure/examples/dist/twrmodworker.8f60cbfd.js | 2 + .../dist/twrmodworker.8f60cbfd.js.map | 1 + azure/examples/dist/twrmodworker.de32dc19.js | 2 - .../dist/twrmodworker.de32dc19.js.map | 1 - azure/examples/fft/kiss_fft.wasm | Bin 24738 -> 24770 bytes .../function-calls/function-calls-a.wasm | Bin 200456 -> 202235 bytes .../function-calls/function-calls.wasm | Bin 200318 -> 202097 bytes azure/examples/helloworld/helloworld.wasm | Bin 21633 -> 21665 bytes azure/examples/maze/maze.wasm | Bin 33472 -> 33504 bytes azure/examples/stdio-canvas/stdio-canvas.wasm | Bin 27729 -> 27753 bytes azure/examples/stdio-div/stdio-div.wasm | Bin 28655 -> 28693 bytes azure/examples/tests-libcxx/tests-libcxx.wasm | Bin 278815 -> 294102 bytes azure/examples/tests-user/tests-user.wasm | Bin 1213573 -> 1225510 bytes azure/examples/tests/tests-dbg.wasm | Bin 289978 -> 293881 bytes azure/examples/tests/tests.wasm | Bin 67188 -> 67738 bytes azure/lib-js/twrlocale.d.ts | 2 +- azure/lib-js/twrlocale.d.ts.map | 2 +- azure/lib-js/twrlocale.js | 9 ++- azure/lib-js/twrlocale.js.map | 2 +- azure/lib-js/twrmodbase.d.ts.map | 2 +- azure/lib-js/twrmodbase.js | 3 + azure/lib-js/twrmodbase.js.map | 2 +- azure/source/twr-ts/twrlocale.ts | 9 ++- azure/source/twr-ts/twrmodbase.ts | 4 +- include/stdlib.h | 4 +- include/twr-crt.h | 1 + include/twr-jsimports.h | 2 +- include/uchar.h | 28 ++++++++++ include/whar.h | 12 ++++ lib-c/twr.a | Bin 174395 -> 175326 bytes lib-c/twrd.a | Bin 512355 -> 516970 bytes lib-js/twrlocale.d.ts | 2 +- lib-js/twrlocale.d.ts.map | 2 +- lib-js/twrlocale.js | 9 ++- lib-js/twrlocale.js.map | 2 +- lib-js/twrmodbase.d.ts.map | 2 +- lib-js/twrmodbase.js | 3 + lib-js/twrmodbase.js.map | 2 +- 80 files changed, 168 insertions(+), 112 deletions(-) delete mode 100644 azure/examples/dist/lib-js.30177026.js delete mode 100644 azure/examples/dist/lib-js.30177026.js.map create mode 100644 azure/examples/dist/lib-js.433b837a.js create mode 100644 azure/examples/dist/lib-js.433b837a.js.map create mode 100644 azure/examples/dist/twrmodworker.8f60cbfd.js create mode 100644 azure/examples/dist/twrmodworker.8f60cbfd.js.map delete mode 100644 azure/examples/dist/twrmodworker.de32dc19.js delete mode 100644 azure/examples/dist/twrmodworker.de32dc19.js.map create mode 100644 include/uchar.h create mode 100644 include/whar.h diff --git a/azure/docsite/api/api-c-con/index.html b/azure/docsite/api/api-c-con/index.html index 38e55747..50deba43 100644 --- a/azure/docsite/api/api-c-con/index.html +++ b/azure/docsite/api/api-c-con/index.html @@ -186,7 +186,7 @@
-

Console API for Web Assembly (Streamed and Windowed)

+

Console C API for Web Assembly (Streamed and Windowed)

This section describes twr-wasm's method of providing and abstracting console I/O in Web Assembly Modules.

C character based input/output is abstracted by struct IoConsole.

Consoles can be "tty" aka "streamed", or they can be "windowed" (aka a "terminal").

diff --git a/azure/docsite/api/api-c-d2d/index.html b/azure/docsite/api/api-c-d2d/index.html index a176324f..724e0a29 100644 --- a/azure/docsite/api/api-c-d2d/index.html +++ b/azure/docsite/api/api-c-d2d/index.html @@ -138,7 +138,7 @@
-

2D Draw API for Web Assembly

+

2D Draw C API for Web Assembly

This section describes twr-wasm's C D2D API, which allows your Web Assembly module to call many of the JavaScript Canvas APIs. There is also a C++ canvas wrapper class in the balls example.

Examples

diff --git a/azure/docsite/api/api-c-general/index.html b/azure/docsite/api/api-c-general/index.html index c1259aa4..fd0c99de 100644 --- a/azure/docsite/api/api-c-general/index.html +++ b/azure/docsite/api/api-c-general/index.html @@ -356,7 +356,8 @@

twr_utf8_char_len

int twr_utf8_char_len(const char *str);

twr_utf32_to_code_page

-

Takes a utf32 value (aka unicode code point value), and fills in the passed character array buffer with the character encoding of the utf32 value, using the current locale's LC_CTYPE code page.

+

Takes a utf32 value (aka unicode code point value), and fills in the passed character array buffer with the character encoding of the utf32 value, using the current locale's LC_CTYPE code page. The buffer is 0 terminated.

+

Also see c32rtomb and c16rtomb.

For example:

char strbuf[6];             // max size of utf-8 is 4+terminating zero.  Max size of ASCII or windows 1252 is 1 + terminating zero
 setlocale(LC_ALL, "");  // set to default locale, which will be UTF-8 encoding with local language/region
diff --git a/azure/docsite/api/api-libc++/index.html b/azure/docsite/api/api-libc++/index.html
index ea410afe..06da09a4 100644
--- a/azure/docsite/api/api-libc++/index.html
+++ b/azure/docsite/api/api-libc++/index.html
@@ -135,29 +135,26 @@
                 

libc++ for Web Assembly

This section describes twr-wasm's support for using the standard c++ library libc++ with Web Assembly.

twr-wasm includes libc++ built for Web Assembly and included in the twr-wasm/lib-c folder.

-

You can build twr-wasm projects in C++ with or without libc++.

+

For C++ the use of libc++ is optional. That is you can build twr-wasm projects in C++ with or without libc++.

See the examples tests-libcxx and tests-user for examples of using libc++.

See the balls example for how to create a C++ Web Assembly program without the standard C++ library. The primary advantage to this approach is a bit smaller code size. You don't need to staticly link libc++.

-

twr-wasm's libc++ for Web Assembly was built with these build options:

-
LIBCXX_ENABLE_LOCALIZATION=ON
-LIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON
-LIBCXXABI_ENABLE_STATIC_UNWINDER=ON
-LIBCXXABI_ENABLE_STATIC=ON
+

Some of the key options twr-wasm's libc++ for Web Assembly was built with are these:

+
DLIBCXX_ENABLE_LOCALIZATION=ON 
+DLIBCXX_ENABLE_UNICODE=ON 
+DLIBCXX_ENABLE_RTTI=ON 
+DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON 
 
-LIBCXX_ENABLE_FILESYSTEM=OFF
-LIBCXX_ENABLE_TIME_ZONE_DATABASE=OFF
-LIBCXX_ENABLE_MONOTONIC_CLOCK=OFF
-LIBCXX_ENABLE_RANDOM_DEVICE=OFF
-LIBCXX_ENABLE_UNICODE=OFF
-LIBCXX_ENABLE_WIDE_CHARACTERS=OFF 
-LIBCXX_ENABLE_EXCEPTIONS=OFF
-LIBCXXABI_ENABLE_EXCEPTIONS=OFF
-LIBCXX_ENABLE_RTTI=OFF
-LIBCXX_ENABLE_THREADS=OFF
-LIBCXXABI_ENABLE_THREADS=OFF
-LIBCXXABI_HAS_PTHREAD_API=OFF
-LIBCXX_ENABLE_SHARED=OFF
-LIBCXXABI_ENABLE_SHARED=OFF 
+DCMAKE_BUILD_TYPE=Release       
+DCMAKE_CXX_STANDARD=20 
+
+DLIBCXX_ENABLE_EXCEPTIONS=OFF 
+DLIBCXX_ENABLE_THREADS=OFF 
+DLIBCXX_ENABLE_SHARED=OFF 
+DLIBCXX_ENABLE_WIDE_CHARACTERS=OFF 
+DLIBCXX_ENABLE_FILESYSTEM=OFF 
+DLIBCXX_ENABLE_TIME_ZONE_DATABASE=OFF 
+DLIBCXX_ENABLE_MONOTONIC_CLOCK=OFF 
+DLIBCXX_ENABLE_RANDOM_DEVICE=OFF
 
diff --git a/azure/docsite/gettingstarted/compiler-opts/index.html b/azure/docsite/gettingstarted/compiler-opts/index.html index 4caea295..aeb6a7c4 100644 --- a/azure/docsite/gettingstarted/compiler-opts/index.html +++ b/azure/docsite/gettingstarted/compiler-opts/index.html @@ -55,13 +55,13 @@
  • Compiler, Linker, Memory
  • @@ -143,20 +143,20 @@

    Compiling, Linking, and Memory Options

    This section described how to use clang to compile C/C++ code for Web Assembly, and how to link your files into a .wasm module.

    twr-wasm lets you use clang directly, without a wrapper. This section describes the needed clang compile options and the wasm-ld link options. You can also take a look at the example makefiles.

    -

    clang with C

    +

    C clang Compiler Options Targeting WASM

    When compiling C code with clang for use with wasm and twr-wasm, use these clang options:

     --target=wasm32 -nostdinc -nostdlib -isystem  ../../include
     

    -isystem should point to the folder twr-wasm/include. The option line above uses a relative link to include that works if your project is a sub folder in the examples folder.

    If you installed using npm, then includes are at node_modules/twr-wasm/include (see the installation note on npm).

    You will also need to link to twr.a (explained in the linking section below).

    -

    clang with C++

    +

    C++ clang Compiler Options Targeting WASM

    When compiling C++ code with clang for use with wasm and twr-wasm, use these clang options:

     --target=wasm32 -fno-exceptions -fno-rtti -nostdlibinc -nostdinc -nostdlib -isystem  ../../include
     

    You will also need to link to twr.a and libc++.a (explained in the linking section below).

    Be sure to adjust the path to twr.a, libc++.a, and the include folder as needed (see above note in the C section).

    -

    linking

    +

    wasm-ld Linker Options

    Use the wasm-ld linker directly with twr-wasm.

    All of the twr-wasm functions are staticly linked from the library lib-c/twr.a. There is also a version ( lib-c/twrd.a ) of twr-wasm library available with debug symbols. One of these two static libraries should be added to the list of files to link (normally this is twr.a). Both versions are built with asserts enabled. twr.a is built with -O3. twrd.a is built with -g -O0.

    To use libc++, link to libc++.a (see the tests-libcxx example makefile).

    @@ -169,7 +169,7 @@

    linking

    If Using twrWasmModuleAsync:

    --no-entry --shared-memory --no-check-features --initial-memory=<size> --max-memory=<size>
     
    -

    Memory

    +

    Memory Options for Web Assembly

    You set the memory size for your module (WebAssembly.Memory) using wasm-ld options as follows (this examples sets your wasm memory to 1MB). The memory size should be a multiple of 64*1024 (64K) chunks.

    if using twrWasmModule:

    --initial-memory=1048576 --max-memory=1048576
    diff --git a/azure/docsite/index.html b/azure/docsite/index.html
    index c99a6721..1fe81955 100644
    --- a/azure/docsite/index.html
    +++ b/azure/docsite/index.html
    @@ -54,9 +54,9 @@
         
         
  • On Github
  • -
  • Version 2.0 vs. 1.0 +
  • Version 2 vs. 1
  • -
  • Version 2.0.0 Limitations +
  • Version 2 Limitations
  • Post Feedback
  • @@ -150,7 +150,7 @@

    twr-wasm - Easy C/C++ Web Assembly Modules

    -

    Documentation for twr-wasm Version 2.0.6

    +

    Documentation for twr-wasm Version 2.1.0

    twr-wasm is a simple, lightweight and easy to use library for building C/C++ Web Assembly code directly with clang. It solves some common use cases with less work than the more feature rich emscripten.

    twr-wasm is easy to understand, and has some cool features. You can input and print streaming character i/o to a <div> tag, use a <canvas> element as an ANSI terminal, or use a C/C++ 2D drawing api (that is compatible with JavaScript Canvas APIs) to draw to a <canvas> element. You can run blocking C/C++.

    twr-wasm allows you to run C/C++ code in a web browser. Legacy code, libraries, full applications, or single functions can be integrated with JavaScript and Typescript.

    @@ -235,17 +235,17 @@

    View Live Web Assembly Demos

    On Github

    https://github.com/twiddlingbits/twr-wasm

    -

    Version 2.0 vs. 1.0

    +

    Version 2 vs. 1

      -
    • libc++ for wasm/clang is now available
    • +
    • libc++ built for Web Assembly is included
    • most of the standard C library is now implemented
    • -
    • instructions for source level debugging
    • +
    • instructions for Web Assembly C/C++ source level debugging
    • version of library with debug symbols provided
    • locale, UTF-8, and windows-1252 support
    -

    Version 2.0.0 Limitations

    +

    Version 2 Limitations

      -
    • libc++ not built with threads, rtti, exceptions, unicode, or wide char support
    • +
    • libc++ not built with exceptions enabled
    • some standard C library functions are not 100% implemented
    • Designed to work with a browser. Not tested with or designed to work with node.js
    • Not all of compile-rt is ported (but most bits you need are)
    • @@ -310,5 +310,5 @@

      Post Feedback

      diff --git a/azure/docsite/more/debugging/index.html b/azure/docsite/more/debugging/index.html index 5c17cec0..1765347c 100644 --- a/azure/docsite/more/debugging/index.html +++ b/azure/docsite/more/debugging/index.html @@ -130,12 +130,12 @@
      -

      Debugging

      +

      Debugging Web Assembly

      This section describes some tips for debugging your Web Assembly (asm) program.

      -

      Debug & Release libs

      +

      Debug and Release libraries

      There are release (twr.a) and debug (twrd.a) versions of the twr-wasm C library. See the examples for use of both. The "debug" version has debug symbols enabled and is built with -O0. The "release" version has no debug symbols and optimization is set to -O3. Both have asserts enabled. In general, you should use the "release" version unless you wish to step through the twr-wasm source -- in which case use the "debug" version.

      libc++.a is not built with debug symbols.

      -

      C/C++ Source Level Debugging

      +

      Source Level Debugging Web Assembly C/C++

      In order to enable C/C++ source debugging with wasm and clang, do the following:

      1. Use Chrome
      2. @@ -148,7 +148,7 @@

        C/C++ Source Level Debugging

      3. you need to ensure that the web server/browser can find the source code
      4. also see Example Readme
      -

      Useful Functions

      +

      Useful twr-wasm Debug Functions

      Use twr_conlog to print 'printf' style to the JavaScript console from C (reference is elsewhere in this doc.)

      #include "twr-wasm.h"
      @@ -156,7 +156,7 @@ 

      Useful Functions

      twr_conlog("hello 99 in hex: %x",99);

      Use twrWasmModule.divLog() to print to a div inside JavaScript code (reference is elsewhere in this doc.)

      -

      Testing Without a Web Server

      +

      Testing Web Assembly Without a Web Server

      Note: If you use this technique, you will not be able to get the c/C++ DevTool chrome extension to run, and so source level debugging won't work.

      You can execute and debug JavaScript with wasm from local files without an HTTP server. It might be helpful to download the twr-wasm source code from github when you do this (so you can step through the twr-wasm typescript code as needed).

      diff --git a/azure/docsite/search/search_index.json b/azure/docsite/search/search_index.json index d6abf6db..334e01cb 100644 --- a/azure/docsite/search/search_index.json +++ b/azure/docsite/search/search_index.json @@ -1 +1 @@ -{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"twr-wasm - Easy C/C++ Web Assembly Modules Documentation for twr-wasm Version 2.0.6 twr-wasm is a simple, lightweight and easy to use library for building C/C++ Web Assembly code directly with clang. It solves some common use cases with less work than the more feature rich emscripten. twr-wasm is easy to understand, and has some cool features. You can input and print streaming character i/o to a
      tag, use a element as an ANSI terminal, or use a C/C++ 2D drawing api (that is compatible with JavaScript Canvas APIs) to draw to a element. You can run blocking C/C++. twr-wasm allows you to run C/C++ code in a web browser. Legacy code, libraries, full applications, or single functions can be integrated with JavaScript and Typescript. twr-wasm is designed to be used with the standard llvm clang compiler and tools. twr-wasm was previously named tiny-wasm-runtime. View C++ Web Assembly Bouncing Ball Demo View bouncing balls here Key Features compile and link C/C++ for use with web assembly using clang directly standard C library, libc++. and purpose built APIs available from C/C++ TypeScrpt/JavaScript classes to load WASM modules and call C/C++ functions localization support, UTF-8, and windows-1252 support in C/C++, print and get characters to/from
      tags in your HTML page in C/C++, print and get characters to/from a based \"terminal\" in C/C++ use 2D drawing API compatible with JavaScript Canvas in C/C++, use the \"blocking loop\" pattern and integrate with Javascript's asynchronous event loop Why? WASM Runtime Limitations section explains why a library like twr-wasm is needed to use Web Assembly. Hello World Here is the simplest twr-wasm example. C code: #include void hello() { printf(\"hello world\\n\"); } index.html: Hello World
      View Live Web Assembly Demos Name View Live Link Source Link Bouncing Balls (C++) View bouncing balls Source for balls Maze (Win32 C Port) View live maze Source for maze Input from
      View square demo Source Mini-Terminal (hello world using ) View demo Source Mini-Terminal (\"cli\" using libc++ and ) View console Source On Github https://github.com/twiddlingbits/twr-wasm Version 2.0 vs. 1.0 libc++ for wasm/clang is now available most of the standard C library is now implemented instructions for source level debugging version of library with debug symbols provided locale, UTF-8, and windows-1252 support Version 2.0.0 Limitations libc++ not built with threads, rtti, exceptions, unicode, or wide char support some standard C library functions are not 100% implemented Designed to work with a browser. Not tested with or designed to work with node.js Not all of compile-rt is ported (but most bits you need are) The following non-compatible changes since 1.0 (relatively minor) there is no longer 'twr_' prefixed std c lib functions (use the normal std c lib names) most 'twr_wasm_' prefixed functions have been shortened to 'twr_'. some functions were renamed or changed slightly to be more consistent, but no functionality is lost. Post Feedback Please post feedback (it worked for you, didn't work, requests, questions, etc) at https://github.com/twiddlingbits/twr-wasm/","title":"Home"},{"location":"#twr-wasm-easy-cc-web-assembly-modules","text":"Documentation for twr-wasm Version 2.0.6 twr-wasm is a simple, lightweight and easy to use library for building C/C++ Web Assembly code directly with clang. It solves some common use cases with less work than the more feature rich emscripten. twr-wasm is easy to understand, and has some cool features. You can input and print streaming character i/o to a
      tag, use a element as an ANSI terminal, or use a C/C++ 2D drawing api (that is compatible with JavaScript Canvas APIs) to draw to a element. You can run blocking C/C++. twr-wasm allows you to run C/C++ code in a web browser. Legacy code, libraries, full applications, or single functions can be integrated with JavaScript and Typescript. twr-wasm is designed to be used with the standard llvm clang compiler and tools. twr-wasm was previously named tiny-wasm-runtime.","title":"twr-wasm - Easy C/C++ Web Assembly Modules"},{"location":"#view-c-web-assembly-bouncing-ball-demo","text":"View bouncing balls here","title":"View C++ Web Assembly Bouncing Ball Demo"},{"location":"#key-features","text":"compile and link C/C++ for use with web assembly using clang directly standard C library, libc++. and purpose built APIs available from C/C++ TypeScrpt/JavaScript classes to load WASM modules and call C/C++ functions localization support, UTF-8, and windows-1252 support in C/C++, print and get characters to/from
      tags in your HTML page in C/C++, print and get characters to/from a based \"terminal\" in C/C++ use 2D drawing API compatible with JavaScript Canvas in C/C++, use the \"blocking loop\" pattern and integrate with Javascript's asynchronous event loop","title":"Key Features"},{"location":"#why","text":"WASM Runtime Limitations section explains why a library like twr-wasm is needed to use Web Assembly.","title":"Why?"},{"location":"#hello-world","text":"Here is the simplest twr-wasm example. C code: #include void hello() { printf(\"hello world\\n\"); } index.html: Hello World
      ","title":"Hello World"},{"location":"#view-live-web-assembly-demos","text":"Name View Live Link Source Link Bouncing Balls (C++) View bouncing balls Source for balls Maze (Win32 C Port) View live maze Source for maze Input from
      View square demo Source Mini-Terminal (hello world using ) View demo Source Mini-Terminal (\"cli\" using libc++ and ) View console Source","title":"View Live Web Assembly Demos"},{"location":"#on-github","text":"https://github.com/twiddlingbits/twr-wasm","title":"On Github"},{"location":"#version-20-vs-10","text":"libc++ for wasm/clang is now available most of the standard C library is now implemented instructions for source level debugging version of library with debug symbols provided locale, UTF-8, and windows-1252 support","title":"Version 2.0 vs. 1.0"},{"location":"#version-200-limitations","text":"libc++ not built with threads, rtti, exceptions, unicode, or wide char support some standard C library functions are not 100% implemented Designed to work with a browser. Not tested with or designed to work with node.js Not all of compile-rt is ported (but most bits you need are) The following non-compatible changes since 1.0 (relatively minor) there is no longer 'twr_' prefixed std c lib functions (use the normal std c lib names) most 'twr_wasm_' prefixed functions have been shortened to 'twr_'. some functions were renamed or changed slightly to be more consistent, but no functionality is lost.","title":"Version 2.0.0 Limitations"},{"location":"#post-feedback","text":"Please post feedback (it worked for you, didn't work, requests, questions, etc) at https://github.com/twiddlingbits/twr-wasm/","title":"Post Feedback"},{"location":"api/api-c-con/","text":"Console API for Web Assembly (Streamed and Windowed) This section describes twr-wasm's method of providing and abstracting console I/O in Web Assembly Modules. C character based input/output is abstracted by struct IoConsole . Consoles can be \"tty\" aka \"streamed\", or they can be \"windowed\" (aka a \"terminal\"). Also see stdio Examples Name View Live Link Source Link \"terminal\" in/out with a View mini-term demo Source Getting stderr,stdin, stdout stdio.h defines stdin , stdout , stderr as explained here: stdio stdio.h also defines FILE like this: typedef struct IoConsole FILE; from : #define stderr (FILE *)(twr_get_stderr_con()) #define stdin (FILE *)(twr_get_stdio_con()) #define stdout (FILE *)(twr_get_stdio_con()) Getting a new console stdin and stdout are set as explaind here . However, in unusual cases you might want to access the various consoles directly, regardless of how stdin, stdout, or stderr are set. You can do so like this: io_nullcon Returns an IoConsole that goes to the bit bucket. io_getc32 will return 0. #include \"twr-io.h\" struct IoConsole* io_nullcon(void); twr_debugcon Returns an IoConsole that goes to the browser's debug console. #include \"twr-crt.h\" struct IoConsole* twr_debugcon(void); twr_divcon Returns an IoConsole that goes to
      , if it exists. #include \"twr-crt.h\" struct IoConsole* twr_divcon(void); twr_windowcon Returns an IoConsole that goes to , if it exists. NOTE: Only one call can be made to this function, and it is usually made by the twr-wasm C runtime, so you likely won't call this function. #include \"twr-crt.h\" struct IoConsole* twr_windowcon(void); IO Console Functions io_putc Sends a byte to an IoConsole and supports the current locale's character encoding. This function will \"stream\" using the current code page. In other words, if you io_putc ASCII, it will work as \"normal\". If the current locale is set to 1252, then you can send windows-1252 encoded characters. If the current locale is UTF-8, then you can stream UTF-8 (that is, call io_putc once for each byte of the multi-byte UTF-8 character). Note that when characters are sent to the browser console using stderr they will not render to the console until a newline, return, or ASCII 03 (End-of-Text) is sent. #include \"twr-io.h\" void io_putc(struct IoConsole* io, unsigned char c); io_putstr Calls io_putc for each byte in the passed string. #include \"twr-io.h\" void io_putstr(struct IoConsole* io, const char* s); io_printf Identical to fprintf , however io_printf will call io_begin_draw and io_end_draw around its drawing activities -- resulting in snapper performance. For example: #include \"twr-io.h\" io_printf(twr_debugcon(), \"hello over there in browser debug console land\\n\"); or #include #include io_printf(stdout, \"hello world\\n\"); #include void io_printf(struct IoConsole *io, const char *format, ...); io_getc32 Waits for the user to enter and then returns a unicode code point. Currently only really works with an IoConsole that is stdin. To return characters encoded with the current locale, see io_mbgetc #include int io_getc32(struct IoConsole* io); io_mbgetc io_mbgetc will get a character from stdin and encode it using the character encoding of the LC_CTYPE category of the current locale. \"C\" will use ASCII. UTF-8 and windows-1252 are also supported. #include void io_mbgetc(struct IoConsole* io, char* strout); io_mbgets Gets a string from an IoConsole (which needs to be stdin). Returns when the user presses \"Enter\". Displays a cursor character and echos the inputted characters, at the current cursor position. Uses character encoding of LC_TYPE of current locale. #include char *io_mbgets(struct IoConsole* io, char *buffer ); io_get_cursor Returns an integer of the current cursor position. The cursor is where the next io_putc is going to go. For windowed consoles, the cursor position ranges from [0, width*height-1], inclusive. #include int io_get_cursor(struct IoConsole* io); io_set_colors For windowed consoles only. Sets a 24 bit RGB default color for the foreground and background. The prior default colors are changed (lost). For example, if you set the default colors when you created the window (see stdio ), the defaults will no longer be active. Use io_get_colors to save existing colors for later restoration using io_set_colors . A call to io_set_colors doesn't actually cause any on screen changes. Instead, these new default colors are used in future draw and text calls. A foreground and background color is set for each cell in the console window. The cell's colors are set to these default foreground/background colors when a call to io_setc , io_setreset , etc is made. #include void io_set_colors(struct IoConsole* io, unsigned long foreground, unsigned long background); io_get_colors For windowed consoles only. Gets the current default colors. #include void io_get_colors(struct IoConsole* io, unsigned long *foreground, unsigned long *background); io_cls For windowed consoles only. Clears the screen. That is, all character cells in the window are set to a space, their colors are reset to the current default colors (see io_set_colors ). #include void io_cls(struct IoConsoleWindow* iow); io_setc For windowed consoles only. Sets a window cell to a character. Sends a byte to an IoConsole and supports the current locale's character encoding. This function will \"stream\" using the current code page. In other words, if you io_setc ASCII, it will work as \"normal\". If the current locale is set to 1252, then you can send windows-1252 encoded characters. If the current locale is UTF-8, then you can stream UTF-8 (that is, call io_setc once for each byte of the multi-byte UTF-8 character). #include bool io_setc(struct IoConsoleWindow* iow, int location, unsigned char c); io_setc32 For windowed consoles only. Sets a window cell to a unicode code point. The colors are set to the defaults (see io_set_colors ). #include void io_setc32(struct IoConsoleWindow* iow, int location, int c); io_setreset For windowed consoles only. Sets or resets (clears) a chunky graphics \"pixel\". Each character cell can also be a 2x3 grid of graphic \"pixels\". In other words, the terminal window has pixel dimensions of width 2 x height 3. The color will be set to the defaults if the impacted cell is not a graphics cell. If it is an existing graphics cell, the colors don't change. See the stdio-canvas example. #include bool io_setreset(struct IoConsoleWindow* iow, int x, int y, bool isset); io_point For windowed consoles only. Checks if a chunky graphics \"pixel\" is set or clear. See io_setreset . #include bool io_point(struct IoConsoleWindow* iow, int x, int y); io_set_cursor Moves the cursor. See io_get_cursor . #include void io_set_cursor(struct IoConsoleWindow* iow, int loc); io_begin_draw For windowed consoles only. This call (and its matching io_end_draw) are not required. But if you bracket any call sequence that draws to the terminal window with an io_begin_draw and io_end_draw , the updates will be batched into one update. io_begin_draw can be nested. This will increase performance and usually prevents the user from seeing partial updates. See the terminal-window io_canvas example. #include void io_begin_draw(struct IoConsole* io); io_end_draw For windowed consoles only. See io_begin_draw . #include void io_end_draw(struct IoConsole* io);","title":"C Console I/O"},{"location":"api/api-c-con/#console-api-for-web-assembly-streamed-and-windowed","text":"This section describes twr-wasm's method of providing and abstracting console I/O in Web Assembly Modules. C character based input/output is abstracted by struct IoConsole . Consoles can be \"tty\" aka \"streamed\", or they can be \"windowed\" (aka a \"terminal\"). Also see stdio","title":"Console API for Web Assembly (Streamed and Windowed)"},{"location":"api/api-c-con/#examples","text":"Name View Live Link Source Link \"terminal\" in/out with a View mini-term demo Source","title":"Examples"},{"location":"api/api-c-con/#getting-stderrstdin-stdout","text":"stdio.h defines stdin , stdout , stderr as explained here: stdio stdio.h also defines FILE like this: typedef struct IoConsole FILE; from : #define stderr (FILE *)(twr_get_stderr_con()) #define stdin (FILE *)(twr_get_stdio_con()) #define stdout (FILE *)(twr_get_stdio_con())","title":"Getting stderr,stdin, stdout"},{"location":"api/api-c-con/#getting-a-new-console","text":"stdin and stdout are set as explaind here . However, in unusual cases you might want to access the various consoles directly, regardless of how stdin, stdout, or stderr are set. You can do so like this:","title":"Getting a new console"},{"location":"api/api-c-con/#io_nullcon","text":"Returns an IoConsole that goes to the bit bucket. io_getc32 will return 0. #include \"twr-io.h\" struct IoConsole* io_nullcon(void);","title":"io_nullcon"},{"location":"api/api-c-con/#twr_debugcon","text":"Returns an IoConsole that goes to the browser's debug console. #include \"twr-crt.h\" struct IoConsole* twr_debugcon(void);","title":"twr_debugcon"},{"location":"api/api-c-con/#twr_divcon","text":"Returns an IoConsole that goes to
      , if it exists. #include \"twr-crt.h\" struct IoConsole* twr_divcon(void);","title":"twr_divcon"},{"location":"api/api-c-con/#twr_windowcon","text":"Returns an IoConsole that goes to , if it exists. NOTE: Only one call can be made to this function, and it is usually made by the twr-wasm C runtime, so you likely won't call this function. #include \"twr-crt.h\" struct IoConsole* twr_windowcon(void);","title":"twr_windowcon"},{"location":"api/api-c-con/#io-console-functions","text":"","title":"IO Console Functions"},{"location":"api/api-c-con/#io_putc","text":"Sends a byte to an IoConsole and supports the current locale's character encoding. This function will \"stream\" using the current code page. In other words, if you io_putc ASCII, it will work as \"normal\". If the current locale is set to 1252, then you can send windows-1252 encoded characters. If the current locale is UTF-8, then you can stream UTF-8 (that is, call io_putc once for each byte of the multi-byte UTF-8 character). Note that when characters are sent to the browser console using stderr they will not render to the console until a newline, return, or ASCII 03 (End-of-Text) is sent. #include \"twr-io.h\" void io_putc(struct IoConsole* io, unsigned char c);","title":"io_putc"},{"location":"api/api-c-con/#io_putstr","text":"Calls io_putc for each byte in the passed string. #include \"twr-io.h\" void io_putstr(struct IoConsole* io, const char* s);","title":"io_putstr"},{"location":"api/api-c-con/#io_printf","text":"Identical to fprintf , however io_printf will call io_begin_draw and io_end_draw around its drawing activities -- resulting in snapper performance. For example: #include \"twr-io.h\" io_printf(twr_debugcon(), \"hello over there in browser debug console land\\n\"); or #include #include io_printf(stdout, \"hello world\\n\"); #include void io_printf(struct IoConsole *io, const char *format, ...);","title":"io_printf"},{"location":"api/api-c-con/#io_getc32","text":"Waits for the user to enter and then returns a unicode code point. Currently only really works with an IoConsole that is stdin. To return characters encoded with the current locale, see io_mbgetc #include int io_getc32(struct IoConsole* io);","title":"io_getc32"},{"location":"api/api-c-con/#io_mbgetc","text":"io_mbgetc will get a character from stdin and encode it using the character encoding of the LC_CTYPE category of the current locale. \"C\" will use ASCII. UTF-8 and windows-1252 are also supported. #include void io_mbgetc(struct IoConsole* io, char* strout);","title":"io_mbgetc"},{"location":"api/api-c-con/#io_mbgets","text":"Gets a string from an IoConsole (which needs to be stdin). Returns when the user presses \"Enter\". Displays a cursor character and echos the inputted characters, at the current cursor position. Uses character encoding of LC_TYPE of current locale. #include char *io_mbgets(struct IoConsole* io, char *buffer );","title":"io_mbgets"},{"location":"api/api-c-con/#io_get_cursor","text":"Returns an integer of the current cursor position. The cursor is where the next io_putc is going to go. For windowed consoles, the cursor position ranges from [0, width*height-1], inclusive. #include int io_get_cursor(struct IoConsole* io);","title":"io_get_cursor"},{"location":"api/api-c-con/#io_set_colors","text":"For windowed consoles only. Sets a 24 bit RGB default color for the foreground and background. The prior default colors are changed (lost). For example, if you set the default colors when you created the window (see stdio ), the defaults will no longer be active. Use io_get_colors to save existing colors for later restoration using io_set_colors . A call to io_set_colors doesn't actually cause any on screen changes. Instead, these new default colors are used in future draw and text calls. A foreground and background color is set for each cell in the console window. The cell's colors are set to these default foreground/background colors when a call to io_setc , io_setreset , etc is made. #include void io_set_colors(struct IoConsole* io, unsigned long foreground, unsigned long background);","title":"io_set_colors"},{"location":"api/api-c-con/#io_get_colors","text":"For windowed consoles only. Gets the current default colors. #include void io_get_colors(struct IoConsole* io, unsigned long *foreground, unsigned long *background);","title":"io_get_colors"},{"location":"api/api-c-con/#io_cls","text":"For windowed consoles only. Clears the screen. That is, all character cells in the window are set to a space, their colors are reset to the current default colors (see io_set_colors ). #include void io_cls(struct IoConsoleWindow* iow);","title":"io_cls"},{"location":"api/api-c-con/#io_setc","text":"For windowed consoles only. Sets a window cell to a character. Sends a byte to an IoConsole and supports the current locale's character encoding. This function will \"stream\" using the current code page. In other words, if you io_setc ASCII, it will work as \"normal\". If the current locale is set to 1252, then you can send windows-1252 encoded characters. If the current locale is UTF-8, then you can stream UTF-8 (that is, call io_setc once for each byte of the multi-byte UTF-8 character). #include bool io_setc(struct IoConsoleWindow* iow, int location, unsigned char c);","title":"io_setc"},{"location":"api/api-c-con/#io_setc32","text":"For windowed consoles only. Sets a window cell to a unicode code point. The colors are set to the defaults (see io_set_colors ). #include void io_setc32(struct IoConsoleWindow* iow, int location, int c);","title":"io_setc32"},{"location":"api/api-c-con/#io_setreset","text":"For windowed consoles only. Sets or resets (clears) a chunky graphics \"pixel\". Each character cell can also be a 2x3 grid of graphic \"pixels\". In other words, the terminal window has pixel dimensions of width 2 x height 3. The color will be set to the defaults if the impacted cell is not a graphics cell. If it is an existing graphics cell, the colors don't change. See the stdio-canvas example. #include bool io_setreset(struct IoConsoleWindow* iow, int x, int y, bool isset);","title":"io_setreset"},{"location":"api/api-c-con/#io_point","text":"For windowed consoles only. Checks if a chunky graphics \"pixel\" is set or clear. See io_setreset . #include bool io_point(struct IoConsoleWindow* iow, int x, int y);","title":"io_point"},{"location":"api/api-c-con/#io_set_cursor","text":"Moves the cursor. See io_get_cursor . #include void io_set_cursor(struct IoConsoleWindow* iow, int loc);","title":"io_set_cursor"},{"location":"api/api-c-con/#io_begin_draw","text":"For windowed consoles only. This call (and its matching io_end_draw) are not required. But if you bracket any call sequence that draws to the terminal window with an io_begin_draw and io_end_draw , the updates will be batched into one update. io_begin_draw can be nested. This will increase performance and usually prevents the user from seeing partial updates. See the terminal-window io_canvas example. #include void io_begin_draw(struct IoConsole* io);","title":"io_begin_draw"},{"location":"api/api-c-con/#io_end_draw","text":"For windowed consoles only. See io_begin_draw . #include void io_end_draw(struct IoConsole* io);","title":"io_end_draw"},{"location":"api/api-c-d2d/","text":"2D Draw API for Web Assembly This section describes twr-wasm's C D2D API, which allows your Web Assembly module to call many of the JavaScript Canvas APIs. There is also a C++ canvas wrapper class in the balls example. Examples Name View Live Link Source Link Bouncing Balls (C++) View bouncing balls Source for balls Maze (Win32 C Port) View live maze here Source for maze Overview Add a canvas tag to your HTML named twr_d2dcanvas like this example (you can use any width/height you like): To draw using the C API: - call d2d_start_draw_sequence() - call draw commands, like d2d_fillrect() - call d2d_end_draw_sequence() Commands are queued until flush'd, which will take the batch of queued draw cmds, and execute them. In the case of twrWasmModuleAsync, the batch of commands is sent over to the JavaScript main thread for execution. By batching the calls, performance is improved. Flush() waits for the commands to finish execution before returning. Flush() is called automatically by d2d_end_draw_sequence(). You pass an argument to d2d_start_draw_sequence() specifying how many instructions will trigger an automatic flush. You can make this larger for efficiency, or smaller if you want to see the render progress with more frequently. There is no limit on the size of the queue, except memory used in the wasm module. There is a flush() function that you can manually call, but it is not normally needed, unless you would like to ensure a sequence renders before d2d_end_draw_sequence() is called, or before the count passed d2d_start_draw_sequence() is met. If you are using twrWasmModuleAsync, or if you are re-rendering the entire frame for each animation update, you should ensure that all of your draws for a single complete frame are made without a call to flush() in the middle of the draw operations, as this may cause flashing. Functions These are the Canvas APIs currently available in C: struct d2d_draw_seq* d2d_start_draw_sequence(int flush_at_ins_count); void d2d_end_draw_sequence(struct d2d_draw_seq* ds); void d2d_flush(struct d2d_draw_seq* ds); int d2d_get_canvas_prop(const char* prop); void d2d_fillrect(struct d2d_draw_seq* ds, double x, double y, double w, double h); void d2d_strokerect(struct d2d_draw_seq* ds, double x, double y, double w, double h); void d2d_filltext(struct d2d_draw_seq* ds, const char* str, double x, double y); void d2d_fillcodepoint(struct d2d_draw_seq* ds, char c, double x, double y); void d2d_measuretext(struct d2d_draw_seq* ds, const char* str, struct d2d_text_metrics *tm); void d2d_save(struct d2d_draw_seq* ds); void d2d_restore(struct d2d_draw_seq* ds); void d2d_setlinewidth(struct d2d_draw_seq* ds, double width); void d2d_setfillstylergba(struct d2d_draw_seq* ds, unsigned long color); void d2d_setstrokestylergba(struct d2d_draw_seq* ds, unsigned long color); void d2d_setfillstyle(struct d2d_draw_seq* ds, const char* css_color); void d2d_setstrokestyle(struct d2d_draw_seq* ds, const char* css_color); void d2d_setfont(struct d2d_draw_seq* ds, const char* font); void d2d_createlineargradient(struct d2d_draw_seq* ds, long id, double x0, double y0, double x1, double y1); void d2d_createradialgradient(struct d2d_draw_seq* ds, long id, double x0, double y0, double radius0, double x1, double y1, double radius1); void d2d_addcolorstop(struct d2d_draw_seq* ds, long gradID, long position, const char* csscolor); void d2d_setfillstylegradient(struct d2d_draw_seq* ds, long gradID); void d2d_releaseid(struct d2d_draw_seq* ds, long id); void d2d_beginpath(struct d2d_draw_seq* ds); void d2d_fill(struct d2d_draw_seq* ds); void d2d_stroke(struct d2d_draw_seq* ds); void d2d_moveto(struct d2d_draw_seq* ds, double x, double y); void d2d_lineto(struct d2d_draw_seq* ds, double x, double y); void d2d_arc(struct d2d_draw_seq* ds, double x, double y, double radius, double start_angle, double end_angle, bool counterclockwise); void d2d_bezierto(struct d2d_draw_seq* ds, double cp1x, double cp1y, double cp2x, double cp2y, double x, double y); void d2d_imagedata(struct d2d_draw_seq* ds, long id, void* mem, unsigned long length, unsigned long width, unsigned long height); void d2d_putimagedata(struct d2d_draw_seq* ds, long id, unsigned long dx, unsigned long dy); void d2d_putimagedatadirty(struct d2d_draw_seq* ds, long id, unsigned long dx, unsigned long dy, unsigned long dirtyX, unsigned long dirtyY, unsigned long dirtyWidth, unsigned long dirtyHeight); d2d_measuretext() returns this structure: struct d2d_text_metrics { double actualBoundingBoxAscent; double actualBoundingBoxDescent; double actualBoundingBoxLeft; double actualBoundingBoxRight; double fontBoundingBoxAscent; double fontBoundingBoxDescent; double width; }; d2d_get_canvas_prop() returns a value of: export interface ICanvasProps { charWidth: number, charHeight: number, foreColor: number, backColor: number, widthInChars: number, heightInChars: number, canvasWidth:number, canvasHeight:number }","title":"C Draw 2D"},{"location":"api/api-c-d2d/#2d-draw-api-for-web-assembly","text":"This section describes twr-wasm's C D2D API, which allows your Web Assembly module to call many of the JavaScript Canvas APIs. There is also a C++ canvas wrapper class in the balls example.","title":"2D Draw API for Web Assembly"},{"location":"api/api-c-d2d/#examples","text":"Name View Live Link Source Link Bouncing Balls (C++) View bouncing balls Source for balls Maze (Win32 C Port) View live maze here Source for maze","title":"Examples"},{"location":"api/api-c-d2d/#overview","text":"Add a canvas tag to your HTML named twr_d2dcanvas like this example (you can use any width/height you like): To draw using the C API: - call d2d_start_draw_sequence() - call draw commands, like d2d_fillrect() - call d2d_end_draw_sequence() Commands are queued until flush'd, which will take the batch of queued draw cmds, and execute them. In the case of twrWasmModuleAsync, the batch of commands is sent over to the JavaScript main thread for execution. By batching the calls, performance is improved. Flush() waits for the commands to finish execution before returning. Flush() is called automatically by d2d_end_draw_sequence(). You pass an argument to d2d_start_draw_sequence() specifying how many instructions will trigger an automatic flush. You can make this larger for efficiency, or smaller if you want to see the render progress with more frequently. There is no limit on the size of the queue, except memory used in the wasm module. There is a flush() function that you can manually call, but it is not normally needed, unless you would like to ensure a sequence renders before d2d_end_draw_sequence() is called, or before the count passed d2d_start_draw_sequence() is met. If you are using twrWasmModuleAsync, or if you are re-rendering the entire frame for each animation update, you should ensure that all of your draws for a single complete frame are made without a call to flush() in the middle of the draw operations, as this may cause flashing.","title":"Overview"},{"location":"api/api-c-d2d/#functions","text":"These are the Canvas APIs currently available in C: struct d2d_draw_seq* d2d_start_draw_sequence(int flush_at_ins_count); void d2d_end_draw_sequence(struct d2d_draw_seq* ds); void d2d_flush(struct d2d_draw_seq* ds); int d2d_get_canvas_prop(const char* prop); void d2d_fillrect(struct d2d_draw_seq* ds, double x, double y, double w, double h); void d2d_strokerect(struct d2d_draw_seq* ds, double x, double y, double w, double h); void d2d_filltext(struct d2d_draw_seq* ds, const char* str, double x, double y); void d2d_fillcodepoint(struct d2d_draw_seq* ds, char c, double x, double y); void d2d_measuretext(struct d2d_draw_seq* ds, const char* str, struct d2d_text_metrics *tm); void d2d_save(struct d2d_draw_seq* ds); void d2d_restore(struct d2d_draw_seq* ds); void d2d_setlinewidth(struct d2d_draw_seq* ds, double width); void d2d_setfillstylergba(struct d2d_draw_seq* ds, unsigned long color); void d2d_setstrokestylergba(struct d2d_draw_seq* ds, unsigned long color); void d2d_setfillstyle(struct d2d_draw_seq* ds, const char* css_color); void d2d_setstrokestyle(struct d2d_draw_seq* ds, const char* css_color); void d2d_setfont(struct d2d_draw_seq* ds, const char* font); void d2d_createlineargradient(struct d2d_draw_seq* ds, long id, double x0, double y0, double x1, double y1); void d2d_createradialgradient(struct d2d_draw_seq* ds, long id, double x0, double y0, double radius0, double x1, double y1, double radius1); void d2d_addcolorstop(struct d2d_draw_seq* ds, long gradID, long position, const char* csscolor); void d2d_setfillstylegradient(struct d2d_draw_seq* ds, long gradID); void d2d_releaseid(struct d2d_draw_seq* ds, long id); void d2d_beginpath(struct d2d_draw_seq* ds); void d2d_fill(struct d2d_draw_seq* ds); void d2d_stroke(struct d2d_draw_seq* ds); void d2d_moveto(struct d2d_draw_seq* ds, double x, double y); void d2d_lineto(struct d2d_draw_seq* ds, double x, double y); void d2d_arc(struct d2d_draw_seq* ds, double x, double y, double radius, double start_angle, double end_angle, bool counterclockwise); void d2d_bezierto(struct d2d_draw_seq* ds, double cp1x, double cp1y, double cp2x, double cp2y, double x, double y); void d2d_imagedata(struct d2d_draw_seq* ds, long id, void* mem, unsigned long length, unsigned long width, unsigned long height); void d2d_putimagedata(struct d2d_draw_seq* ds, long id, unsigned long dx, unsigned long dy); void d2d_putimagedatadirty(struct d2d_draw_seq* ds, long id, unsigned long dx, unsigned long dy, unsigned long dirtyX, unsigned long dirtyY, unsigned long dirtyWidth, unsigned long dirtyHeight); d2d_measuretext() returns this structure: struct d2d_text_metrics { double actualBoundingBoxAscent; double actualBoundingBoxDescent; double actualBoundingBoxLeft; double actualBoundingBoxRight; double fontBoundingBoxAscent; double fontBoundingBoxDescent; double width; }; d2d_get_canvas_prop() returns a value of: export interface ICanvasProps { charWidth: number, charHeight: number, foreColor: number, backColor: number, widthInChars: number, heightInChars: number, canvasWidth:number, canvasHeight:number }","title":"Functions"},{"location":"api/api-c-general/","text":"General C API for WASM Overview This sections describes the \"general\" twr-wasm functions available that don't fit neatly into another category (such as standard C library functions, Draw 2D functions, etc.) These functions often start with \"twr_\" and are generally found in this include file: \\twr-wasm\\include\\twr-crt.h bzero Set a block of memory to zeros. Calls memset(to, 0, count) . #include void bzero (void *to, size_t count); getc This is the standard c library function (see the the standard library docs available on the internet). Of note this function will return extended ASCII (128-255 inclusive). The extend ASCII are always encoded with Windows-1252 encoding. See twr_getc32 for a list of related functions. Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input. twr_atod Similar to stdlib atof . #include \"twr-crt.h\" double twr_atod(const char* str); twr_atou64 Convert a string to a 64 bit unsigned integer, stopping when the first non-valid character is encountered. If len is provided, it will be set to the number of characters read. Radix should be >=2 and <=36 -- for example, 10 is a normal base 10 number and 16 is hexadecimal. #include \"twr-crt.h\" int64_t twr_atou64(const char *str, int* len, int radix); twr_dtoa The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed #include \"twr-crt.h\" void twr_dtoa(char* buffer, int sizeInBytes, double value, int max_precision); twr_cache_malloc/free These functions keep allocated memory in a cache for much faster re-access than the standard malloc/free. #include \"twr-crt.h\" void *twr_cache_malloc(twr_size_t size); void twr_cache_free(void* mem); twr_code_page_to_utf32_streamed Return a unicode code point (aka utf-32 value) when passed a byte stream that represents an encoded character using the current local's LC_CTYPE code page. A zero is returned if the byte stream has not yet completed a decode. For example: int cp setlocale(LC_ALL, \"\"); // set to default locale, which will be UTF-8 encoding with local language/region // turn a UTF-8 Euro into a UTF-32 value cp==twr_code_page_to_utf32_streamed(0xE2); assert (cp==0); cp=twr_code_page_to_utf32_streamed(0x82); assert (cp==0); cp=twr_code_page_to_utf32_streamed(0xAC); assert (cp==0x000020AC); // Euro Code points #include int twr_code_page_to_utf32_streamed(unsigned char byte) twr_conlog twr_conlog prints debug messages to the browser console from your C code. #include \"twr-crt.h\" void twr_conlog(char* format, ...); Each call to twr_conlog() will generate a single call to console.log() in JavaScript to ensure that you see debug prints. This call is identical to printf, except that it adds a newline. The current implementation does not wait for the debug string to output to the console before returning from twr_conlog, when using twrWasmModuleAsync. In this case, it can take a small bit of time for the string to make its way across the Worker Thread boundary. This is normally not a problem and results in faster performance. But if your code crashes soon after the debug print, the print might not appear. If you think this is an issue, you can call twr_sleep(1) after your twr_conlog call. This will force a blocking wait for the print to print. Prior to 1.0, this function was called twr_dbg_printf , and operated slightly differently. twr_epoch_timems Returns the number of milliseconds since the start of the epoch. #include \"twr-wasm.h\" uint64_t twr_epoch_timems(); twr_getc32 Gets a 32 bit unicode code point character from stdin . Unlike the standard C library function getchar , twr_getc32 does not buffer a line (that is, twr_getc32 will return a character before the user presses Enter). twr_getc32 is implemented as: int twr_getc32() { return io_getc32(twr_get_stdio_con()); } Note that stdlib getchar and ungetc are not currently implemented. Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input. Also see: io_mbgets - get a multibyte string from a console using the current locale character encoding twr_mbgets - similar to io_mbgets , except always gets a multibyte locale format string from stdin. io_mbgetc - get a multibyte character from an IoConsole (like stdin ) using the current locale character encoding getc (sames as fgetc ) - get a single byte from a FILE * (IoConsole) -- returning ASCII or extended ASCII (window-1252 encoding) io_getc32 - gets a 32 bit unicode code point from an IoConsole (which currently needs to be stdin) #include \"twr-crt.h\" int twr_getc32(); twr_get_navlang Returns the BCP 47 language tag as found in javacript navigator.language . If len is not null, it will be filled in with the string length of the language tag. #include \"twr-crt.h\" const char* twr_get_navlang(int *len); twr_get_current_locale extern inline locale_t twr_get_current_locale(void); twr_get_current_locale will return the locale that has been set by setlocale . It can be used to pass to a function that takes a locale_t. twr_localize_numeric_string Functions like twr_dtoa do not localize the decimal point. To get a localized decimal point, you can use printf , or alternately twr_localize_numeric_string to post process a string. For example: char b[10]; strcpy(b, \"1.23\"); twr_localize_numeric_string(b, twr_get_current_locale()); // if locale was set to french, then b is now 1,23 #include void twr_localize_numeric_string(char* str, locale_t locale); twr_mem_debug_stats Print memory map and malloc stats to stderr or stdout. (note FILE * is the same as struct IoConsole*) #include void twr_mem_debug_stats(struct IoConsole* outcon); twr_mbgets Gets a string from stdin . The string will be in the current locale's character encoding -- ASCII for \"C\", and either UTF-8 or windows-1252 for \"\". See localization . #include \"twr-crt.h\" char* twr_mbgets(char* buffer); Internally this function uses the stdio IoConsole -- see the IoConsole section for more advanced input/output. This function will encode characters as specified by the LC_CTYPE category of the current locale. ASCII is used for \"C\", and UTF-8 and Windows-1252 are also supported (see localization ) Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input. twr_mbslen_l Returns the number of characters in a string using the character encoding of the passed locale (ASCII for \"C\", UTF-8, or windows-1252 for \"\"). You can use twr_get_current_locale to find the current locale. #include size_t twr_mbslen_l(const char *str, locale_t locale); twr_sleep twr_sleep is a traditional blocking sleep function. This function is blocking, and you must use twrWasmModuleAsync. #include \"twr-wasm.h\" void twr_sleep(int ms); twr_tofixed This function is identical to its JavaScript version. #include \"twr-wasm.h\" void twr_tofixed(char* buffer, int buffer_size, double value, int dec_digits); The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed twr_toexponential This function is identical to its JavaScript version. #include \"twr-wasm.h\" void twr_toexponential(char* buffer, int buffer_size, double value, int dec_digits); The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed twr_strhorizflip Mirror image the passed in string. #include \"twr-crt.h\" void twr_strhorizflip(char * buffer, int n); twr_utf8_char_len Returns the number of bytes in a UTF-8 character (passed as a string pointer). UTF-8 characters can be 1 to 4 bytes in length. #include int twr_utf8_char_len(const char *str); twr_utf32_to_code_page Takes a utf32 value (aka unicode code point value), and fills in the passed character array buffer with the character encoding of the utf32 value, using the current locale's LC_CTYPE code page. For example: char strbuf[6]; // max size of utf-8 is 4+terminating zero. Max size of ASCII or windows 1252 is 1 + terminating zero setlocale(LC_ALL, \"\"); // set to default locale, which will be UTF-8 encoding with local language/region twr_utf32_to_code_page(strbuf, 0x000020AC); // encode a Euro code point printf(\"%s\", strbuf); assert ( strcmp(strbuf,\"\\xE2\\x82\\xAC\")==0 ); // utf-8 encoding of euro assert ( strcmp(strbuf,\"\u20ac\")==0 ); // clang string literals default to utf-8 encoding include void twr_utf32_to_code_page(char* out, int utf32) twr_vprintf Performs a printf by calling the callback with cbdata for each character. #include \"twr-crt.h\" void twr_vprintf(twr_cbprintf_callback out, void* cbdata, const char *format, va_list* args); floating math helpers int twr_isnan(double v); int twr_isinf(double v); double twr_nanval(); double twr_infval();","title":"C General"},{"location":"api/api-c-general/#general-c-api-for-wasm","text":"","title":"General C API for WASM"},{"location":"api/api-c-general/#overview","text":"This sections describes the \"general\" twr-wasm functions available that don't fit neatly into another category (such as standard C library functions, Draw 2D functions, etc.) These functions often start with \"twr_\" and are generally found in this include file: \\twr-wasm\\include\\twr-crt.h","title":"Overview"},{"location":"api/api-c-general/#bzero","text":"Set a block of memory to zeros. Calls memset(to, 0, count) . #include void bzero (void *to, size_t count);","title":"bzero"},{"location":"api/api-c-general/#getc","text":"This is the standard c library function (see the the standard library docs available on the internet). Of note this function will return extended ASCII (128-255 inclusive). The extend ASCII are always encoded with Windows-1252 encoding. See twr_getc32 for a list of related functions. Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input.","title":"getc"},{"location":"api/api-c-general/#twr_atod","text":"Similar to stdlib atof . #include \"twr-crt.h\" double twr_atod(const char* str);","title":"twr_atod"},{"location":"api/api-c-general/#twr_atou64","text":"Convert a string to a 64 bit unsigned integer, stopping when the first non-valid character is encountered. If len is provided, it will be set to the number of characters read. Radix should be >=2 and <=36 -- for example, 10 is a normal base 10 number and 16 is hexadecimal. #include \"twr-crt.h\" int64_t twr_atou64(const char *str, int* len, int radix);","title":"twr_atou64"},{"location":"api/api-c-general/#twr_dtoa","text":"The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed #include \"twr-crt.h\" void twr_dtoa(char* buffer, int sizeInBytes, double value, int max_precision);","title":"twr_dtoa"},{"location":"api/api-c-general/#twr_cache_mallocfree","text":"These functions keep allocated memory in a cache for much faster re-access than the standard malloc/free. #include \"twr-crt.h\" void *twr_cache_malloc(twr_size_t size); void twr_cache_free(void* mem);","title":"twr_cache_malloc/free"},{"location":"api/api-c-general/#twr_code_page_to_utf32_streamed","text":"Return a unicode code point (aka utf-32 value) when passed a byte stream that represents an encoded character using the current local's LC_CTYPE code page. A zero is returned if the byte stream has not yet completed a decode. For example: int cp setlocale(LC_ALL, \"\"); // set to default locale, which will be UTF-8 encoding with local language/region // turn a UTF-8 Euro into a UTF-32 value cp==twr_code_page_to_utf32_streamed(0xE2); assert (cp==0); cp=twr_code_page_to_utf32_streamed(0x82); assert (cp==0); cp=twr_code_page_to_utf32_streamed(0xAC); assert (cp==0x000020AC); // Euro Code points #include int twr_code_page_to_utf32_streamed(unsigned char byte)","title":"twr_code_page_to_utf32_streamed"},{"location":"api/api-c-general/#twr_conlog","text":"twr_conlog prints debug messages to the browser console from your C code. #include \"twr-crt.h\" void twr_conlog(char* format, ...); Each call to twr_conlog() will generate a single call to console.log() in JavaScript to ensure that you see debug prints. This call is identical to printf, except that it adds a newline. The current implementation does not wait for the debug string to output to the console before returning from twr_conlog, when using twrWasmModuleAsync. In this case, it can take a small bit of time for the string to make its way across the Worker Thread boundary. This is normally not a problem and results in faster performance. But if your code crashes soon after the debug print, the print might not appear. If you think this is an issue, you can call twr_sleep(1) after your twr_conlog call. This will force a blocking wait for the print to print. Prior to 1.0, this function was called twr_dbg_printf , and operated slightly differently.","title":"twr_conlog"},{"location":"api/api-c-general/#twr_epoch_timems","text":"Returns the number of milliseconds since the start of the epoch. #include \"twr-wasm.h\" uint64_t twr_epoch_timems();","title":"twr_epoch_timems"},{"location":"api/api-c-general/#twr_getc32","text":"Gets a 32 bit unicode code point character from stdin . Unlike the standard C library function getchar , twr_getc32 does not buffer a line (that is, twr_getc32 will return a character before the user presses Enter). twr_getc32 is implemented as: int twr_getc32() { return io_getc32(twr_get_stdio_con()); } Note that stdlib getchar and ungetc are not currently implemented. Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input. Also see: io_mbgets - get a multibyte string from a console using the current locale character encoding twr_mbgets - similar to io_mbgets , except always gets a multibyte locale format string from stdin. io_mbgetc - get a multibyte character from an IoConsole (like stdin ) using the current locale character encoding getc (sames as fgetc ) - get a single byte from a FILE * (IoConsole) -- returning ASCII or extended ASCII (window-1252 encoding) io_getc32 - gets a 32 bit unicode code point from an IoConsole (which currently needs to be stdin) #include \"twr-crt.h\" int twr_getc32();","title":"twr_getc32"},{"location":"api/api-c-general/#twr_get_navlang","text":"Returns the BCP 47 language tag as found in javacript navigator.language . If len is not null, it will be filled in with the string length of the language tag. #include \"twr-crt.h\" const char* twr_get_navlang(int *len);","title":"twr_get_navlang"},{"location":"api/api-c-general/#twr_get_current_locale","text":"extern inline locale_t twr_get_current_locale(void); twr_get_current_locale will return the locale that has been set by setlocale . It can be used to pass to a function that takes a locale_t.","title":"twr_get_current_locale"},{"location":"api/api-c-general/#twr_localize_numeric_string","text":"Functions like twr_dtoa do not localize the decimal point. To get a localized decimal point, you can use printf , or alternately twr_localize_numeric_string to post process a string. For example: char b[10]; strcpy(b, \"1.23\"); twr_localize_numeric_string(b, twr_get_current_locale()); // if locale was set to french, then b is now 1,23 #include void twr_localize_numeric_string(char* str, locale_t locale);","title":"twr_localize_numeric_string"},{"location":"api/api-c-general/#twr_mem_debug_stats","text":"Print memory map and malloc stats to stderr or stdout. (note FILE * is the same as struct IoConsole*) #include void twr_mem_debug_stats(struct IoConsole* outcon);","title":"twr_mem_debug_stats"},{"location":"api/api-c-general/#twr_mbgets","text":"Gets a string from stdin . The string will be in the current locale's character encoding -- ASCII for \"C\", and either UTF-8 or windows-1252 for \"\". See localization . #include \"twr-crt.h\" char* twr_mbgets(char* buffer); Internally this function uses the stdio IoConsole -- see the IoConsole section for more advanced input/output. This function will encode characters as specified by the LC_CTYPE category of the current locale. ASCII is used for \"C\", and UTF-8 and Windows-1252 are also supported (see localization ) Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input.","title":"twr_mbgets"},{"location":"api/api-c-general/#twr_mbslen_l","text":"Returns the number of characters in a string using the character encoding of the passed locale (ASCII for \"C\", UTF-8, or windows-1252 for \"\"). You can use twr_get_current_locale to find the current locale. #include size_t twr_mbslen_l(const char *str, locale_t locale);","title":"twr_mbslen_l"},{"location":"api/api-c-general/#twr_sleep","text":"twr_sleep is a traditional blocking sleep function. This function is blocking, and you must use twrWasmModuleAsync. #include \"twr-wasm.h\" void twr_sleep(int ms);","title":"twr_sleep"},{"location":"api/api-c-general/#twr_tofixed","text":"This function is identical to its JavaScript version. #include \"twr-wasm.h\" void twr_tofixed(char* buffer, int buffer_size, double value, int dec_digits); The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed","title":"twr_tofixed"},{"location":"api/api-c-general/#twr_toexponential","text":"This function is identical to its JavaScript version. #include \"twr-wasm.h\" void twr_toexponential(char* buffer, int buffer_size, double value, int dec_digits); The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed","title":"twr_toexponential"},{"location":"api/api-c-general/#twr_strhorizflip","text":"Mirror image the passed in string. #include \"twr-crt.h\" void twr_strhorizflip(char * buffer, int n);","title":"twr_strhorizflip"},{"location":"api/api-c-general/#twr_utf8_char_len","text":"Returns the number of bytes in a UTF-8 character (passed as a string pointer). UTF-8 characters can be 1 to 4 bytes in length. #include int twr_utf8_char_len(const char *str);","title":"twr_utf8_char_len"},{"location":"api/api-c-general/#twr_utf32_to_code_page","text":"Takes a utf32 value (aka unicode code point value), and fills in the passed character array buffer with the character encoding of the utf32 value, using the current locale's LC_CTYPE code page. For example: char strbuf[6]; // max size of utf-8 is 4+terminating zero. Max size of ASCII or windows 1252 is 1 + terminating zero setlocale(LC_ALL, \"\"); // set to default locale, which will be UTF-8 encoding with local language/region twr_utf32_to_code_page(strbuf, 0x000020AC); // encode a Euro code point printf(\"%s\", strbuf); assert ( strcmp(strbuf,\"\\xE2\\x82\\xAC\")==0 ); // utf-8 encoding of euro assert ( strcmp(strbuf,\"\u20ac\")==0 ); // clang string literals default to utf-8 encoding include void twr_utf32_to_code_page(char* out, int utf32)","title":"twr_utf32_to_code_page"},{"location":"api/api-c-general/#twr_vprintf","text":"Performs a printf by calling the callback with cbdata for each character. #include \"twr-crt.h\" void twr_vprintf(twr_cbprintf_callback out, void* cbdata, const char *format, va_list* args);","title":"twr_vprintf"},{"location":"api/api-c-general/#floating-math-helpers","text":"int twr_isnan(double v); int twr_isinf(double v); double twr_nanval(); double twr_infval();","title":"floating math helpers"},{"location":"api/api-c-stdlib/","text":"Standard C library for Web Assembly This section describes twr-wasm's support for the Standard C Library. twr-wasm includes its own implementation of the standard C library optimized for Web Assembly and wasm running in a web browser. This is a core feature of twr-wasm. For documentation of these functions, see the many standard C library documentation web sites. The following subset of the standard C library is available. Also see twr-wasm/include folder for include files. stdio.h * fprintf will only work with these -- stderr, stdin, stdout */ /* these return 'struct IoConsole *' which is same as 'FILE *' */ #define stderr (FILE *)(twr_get_stderr_con()) #define stdin (FILE *)(twr_get_stdio_con()) #define stdout (FILE *)(twr_get_stdio_con()) int snprintf(char *buffer, size_t bufsz, const char *format, ... ); int sprintf( char *buffer, const char *format, ... ); int vsnprintf(char *buffer, size_t bufsz, const char *format, va_list vlist); int vasprintf(char **strp, const char* format, va_list vlist ); int printf(const char* format, ...); int vprintf(const char* format, va_list vlist ); int puts(const char *str); int putchar(int c); typedef struct IoConsole FILE; int vfprintf(FILE *stream, const char *format, va_list vlist); int fprintf(FILE *stream, const char* format, ...); size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream); int ferror(FILE *stream); int feof(FILE *stream); int fflush(FILE *stream); int is_terminal(FILE *stream); int fputc(int ch, FILE* stream); int putc(int ch, FILE* stream); int fgetc(FILE *stream ); int getc(FILE *stream); stdlib.h void *malloc(size_t size); void free(void *mem); size_t avail(void); void *realloc( void *ptr, size_t new_size ); void* calloc( size_t num, size_t size ); void *aligned_alloc( size_t alignment, size_t size ); int rand(void); void srand(int seed); #define __min(a,b) (((a) < (b)) ? (a) : (b)) #define __max(a,b) (((a) > (b)) ? (a) : (b)) int _fcvt_s( char* buffer, size_t sizeInBytes, double value, int fracpart_numdigits, int *dec, int *sign ); double atof(const char* str); int atoi(const char *str); long atol( const char *str ); long long atoll( const char *str ); long strtol(const char *str, char **str_end, int base); long long strtoll(const char *str, char **str_end, int base); long long strtoll_l(const char *str, char **str_end, int base, locale_t loc); unsigned long long strtoull(const char *str, char **str_end, int base); unsigned long long strtoull_l(const char *str, char **str_end, int base, locale_t loc); unsigned long strtoul(const char *str, char ** str_end, int base); float strtof(const char *str, char ** str_end); float strtof_l(const char *str, char ** str_end, locale_t locale); double strtod(const char *str, char **str_end); double strtod_l(const char *str, char **str_end, locale_t locale); long double strtold(const char *str, char **str_end); long double strtold_l(const char *str, char **str_end, locale_t locale); int _itoa_s(int64_t value, char * buffer, size_t size, int radix); div_t div( int x, int y ); ldiv_t ldiv( long x, long y ); lldiv_t lldiv( long long x, long long y ); _Noreturn void abort(void); int atexit(void (*func)(void)); Note that _fcvt_s as currently enabled has these limitations: - fractional digits <=100 - values must be less than 1e+21 - values negative exponents must be smaller than 1e-99 There is a full featured version of _fcvt_s in the source code, but is not currently enabled, since the version enabled is smaller and works in most use cases. assert.h void assert(int expression); math.h int abs(int n); double acos(double arg); double asin(double arg); double atan(double arg); double ceil(double arg); double cos(double arg); double exp(double arg); double fabs(double arg); double floor(double arg); double fmod(double x, double y); double log(double arg); double pow(double base, double exp); double sin(double arg); double sqrt(double arg); double tan(double arg); double trunc(double arg); stdarg.h #define va_start(v,l) __builtin_va_start(v,l) #define va_end(v) __builtin_va_end(v) #define va_arg(v,l) __builtin_va_arg(v,l) #define va_copy(d,s) __builtin_va_copy(d,s) typedef __builtin_va_list va_list; ctype.h int isascii(int); int toascii(int); int isalnum(int c); int isalpha(int c); int isblank(int); int iscntrl(int); int isdigit(int c); int isgraph(int c); int islower(int); int isprint(int); int ispunct(int); int isspace(int c); int isupper(int); int isxdigit(int); int tolower(int c); int toupper(int c); int isalnum_l(int c, locale_t loc); int isalpha_l(int c, locale_t loc); int isblank_l(int c, locale_t loc); int iscntrl_l(int c, locale_t loc); int isdigit_l(int c, locale_t loc); int isgraph_l(int c, locale_t loc); int islower_l(int c, locale_t loc); int isprint_l(int c, locale_t loc); int ispunct_l(int c, locale_t loc); int isspace_l(int c, locale_t loc); int isupper_l(int c, locale_t loc); int isxdigit_l(int c, locale_t loc); int tolower_l(int c, locale_t loc); int toupper_l(int c, locale_t loc); _stdtypes.h // don't include directly -- included by various .h files typedef unsigned long size_t; #define MAX_SIZE_T 2147483647 #ifdef __cplusplus #define NULL __null #else #define NULL ((void*)0) #endif typedef struct __locale_t_struct * locale_t; stddef.h #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef double max_align_t; string.h size_t strlen(const char * str); char *strdup(const char * source); char *strcpy(char *dest, const char *source); int strcat_s(char *dest, size_t destsz, const char *src); char* strcat(char *dest, const char *src); char *strncpy(char *dest, const char *source, size_t count); int strcmp(const char* string1, const char* string2); int strncmp(const char* lhs, const char* rhs, size_t count); int stricmp(const char* string1, const char* string2); int strnicmp(const char* string1, const char* string2, size_t count); int strcoll(const char* lhs, const char* rhs); int strcoll_l(const char* lhs, const char* rhs, locale_t loc); char *strchr(const char *str, int ch); void *memchr(const void *ptr, int ch, size_t count); char *strstr(const char *haystack, const char *needle); char * strerror(int errnum ); char * _strerror(const char *strErrMsg); void *memmove(void *dest, const void *src, size_t n); int memcmp( const void* lhs, const void* rhs, size_t count ); void bzero (void *to, size_t count); // implemented in memcpy.wat void *memcpy(void *dest, const void * src, size_t n); void *memset(void *mem, int c, size_t n); time.h typedef unsigned long time_t; unsigned long time(unsigned long *time); size_t strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr); size_t strftime_l(char *s, size_t maxsize, const char *format, const struct tm *timeptr, locale_t locale); struct tm *localtime(const time_t *timer); int gettimeofday(struct timeval *tv, void* notused); #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) #define timercmp(tvp,uvp,cmp) \\ ((tvp)->tv_sec cmp (uvp)->tv_sec || \\ ((tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)) #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 locale.h #define LC_GLOBAL_LOCALE twr_get_current_locale() char* setlocale(int category, const char* locale); struct lconv *localeconv(void); locale_t newlocale(int category_mask, const char *locale, locale_t base); locale_t uselocale(locale_t); void freelocale(locale_t); locale_t duplocale(locale_t); extern inline locale_t twr_get_current_locale(void); errno.h typedef int errno_t; extern int * _errno(void); #define errno (*_errno()) errno_t _set_errno(int _Value); errno_t _get_errno(int *_Value); Other include files available float.h limits.h stdbool.h stdint.h","title":"C Standard C Library"},{"location":"api/api-c-stdlib/#standard-c-library-for-web-assembly","text":"This section describes twr-wasm's support for the Standard C Library. twr-wasm includes its own implementation of the standard C library optimized for Web Assembly and wasm running in a web browser. This is a core feature of twr-wasm. For documentation of these functions, see the many standard C library documentation web sites. The following subset of the standard C library is available. Also see twr-wasm/include folder for include files.","title":"Standard C library for Web Assembly"},{"location":"api/api-c-stdlib/#stdioh","text":"* fprintf will only work with these -- stderr, stdin, stdout */ /* these return 'struct IoConsole *' which is same as 'FILE *' */ #define stderr (FILE *)(twr_get_stderr_con()) #define stdin (FILE *)(twr_get_stdio_con()) #define stdout (FILE *)(twr_get_stdio_con()) int snprintf(char *buffer, size_t bufsz, const char *format, ... ); int sprintf( char *buffer, const char *format, ... ); int vsnprintf(char *buffer, size_t bufsz, const char *format, va_list vlist); int vasprintf(char **strp, const char* format, va_list vlist ); int printf(const char* format, ...); int vprintf(const char* format, va_list vlist ); int puts(const char *str); int putchar(int c); typedef struct IoConsole FILE; int vfprintf(FILE *stream, const char *format, va_list vlist); int fprintf(FILE *stream, const char* format, ...); size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream); int ferror(FILE *stream); int feof(FILE *stream); int fflush(FILE *stream); int is_terminal(FILE *stream); int fputc(int ch, FILE* stream); int putc(int ch, FILE* stream); int fgetc(FILE *stream ); int getc(FILE *stream);","title":"stdio.h"},{"location":"api/api-c-stdlib/#stdlibh","text":"void *malloc(size_t size); void free(void *mem); size_t avail(void); void *realloc( void *ptr, size_t new_size ); void* calloc( size_t num, size_t size ); void *aligned_alloc( size_t alignment, size_t size ); int rand(void); void srand(int seed); #define __min(a,b) (((a) < (b)) ? (a) : (b)) #define __max(a,b) (((a) > (b)) ? (a) : (b)) int _fcvt_s( char* buffer, size_t sizeInBytes, double value, int fracpart_numdigits, int *dec, int *sign ); double atof(const char* str); int atoi(const char *str); long atol( const char *str ); long long atoll( const char *str ); long strtol(const char *str, char **str_end, int base); long long strtoll(const char *str, char **str_end, int base); long long strtoll_l(const char *str, char **str_end, int base, locale_t loc); unsigned long long strtoull(const char *str, char **str_end, int base); unsigned long long strtoull_l(const char *str, char **str_end, int base, locale_t loc); unsigned long strtoul(const char *str, char ** str_end, int base); float strtof(const char *str, char ** str_end); float strtof_l(const char *str, char ** str_end, locale_t locale); double strtod(const char *str, char **str_end); double strtod_l(const char *str, char **str_end, locale_t locale); long double strtold(const char *str, char **str_end); long double strtold_l(const char *str, char **str_end, locale_t locale); int _itoa_s(int64_t value, char * buffer, size_t size, int radix); div_t div( int x, int y ); ldiv_t ldiv( long x, long y ); lldiv_t lldiv( long long x, long long y ); _Noreturn void abort(void); int atexit(void (*func)(void)); Note that _fcvt_s as currently enabled has these limitations: - fractional digits <=100 - values must be less than 1e+21 - values negative exponents must be smaller than 1e-99 There is a full featured version of _fcvt_s in the source code, but is not currently enabled, since the version enabled is smaller and works in most use cases.","title":"stdlib.h"},{"location":"api/api-c-stdlib/#asserth","text":"void assert(int expression);","title":"assert.h"},{"location":"api/api-c-stdlib/#mathh","text":"int abs(int n); double acos(double arg); double asin(double arg); double atan(double arg); double ceil(double arg); double cos(double arg); double exp(double arg); double fabs(double arg); double floor(double arg); double fmod(double x, double y); double log(double arg); double pow(double base, double exp); double sin(double arg); double sqrt(double arg); double tan(double arg); double trunc(double arg);","title":"math.h"},{"location":"api/api-c-stdlib/#stdargh","text":"#define va_start(v,l) __builtin_va_start(v,l) #define va_end(v) __builtin_va_end(v) #define va_arg(v,l) __builtin_va_arg(v,l) #define va_copy(d,s) __builtin_va_copy(d,s) typedef __builtin_va_list va_list;","title":"stdarg.h"},{"location":"api/api-c-stdlib/#ctypeh","text":"int isascii(int); int toascii(int); int isalnum(int c); int isalpha(int c); int isblank(int); int iscntrl(int); int isdigit(int c); int isgraph(int c); int islower(int); int isprint(int); int ispunct(int); int isspace(int c); int isupper(int); int isxdigit(int); int tolower(int c); int toupper(int c); int isalnum_l(int c, locale_t loc); int isalpha_l(int c, locale_t loc); int isblank_l(int c, locale_t loc); int iscntrl_l(int c, locale_t loc); int isdigit_l(int c, locale_t loc); int isgraph_l(int c, locale_t loc); int islower_l(int c, locale_t loc); int isprint_l(int c, locale_t loc); int ispunct_l(int c, locale_t loc); int isspace_l(int c, locale_t loc); int isupper_l(int c, locale_t loc); int isxdigit_l(int c, locale_t loc); int tolower_l(int c, locale_t loc); int toupper_l(int c, locale_t loc);","title":"ctype.h"},{"location":"api/api-c-stdlib/#_stdtypesh","text":"// don't include directly -- included by various .h files typedef unsigned long size_t; #define MAX_SIZE_T 2147483647 #ifdef __cplusplus #define NULL __null #else #define NULL ((void*)0) #endif typedef struct __locale_t_struct * locale_t;","title":"_stdtypes.h"},{"location":"api/api-c-stdlib/#stddefh","text":"#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef double max_align_t;","title":"stddef.h"},{"location":"api/api-c-stdlib/#stringh","text":"size_t strlen(const char * str); char *strdup(const char * source); char *strcpy(char *dest, const char *source); int strcat_s(char *dest, size_t destsz, const char *src); char* strcat(char *dest, const char *src); char *strncpy(char *dest, const char *source, size_t count); int strcmp(const char* string1, const char* string2); int strncmp(const char* lhs, const char* rhs, size_t count); int stricmp(const char* string1, const char* string2); int strnicmp(const char* string1, const char* string2, size_t count); int strcoll(const char* lhs, const char* rhs); int strcoll_l(const char* lhs, const char* rhs, locale_t loc); char *strchr(const char *str, int ch); void *memchr(const void *ptr, int ch, size_t count); char *strstr(const char *haystack, const char *needle); char * strerror(int errnum ); char * _strerror(const char *strErrMsg); void *memmove(void *dest, const void *src, size_t n); int memcmp( const void* lhs, const void* rhs, size_t count ); void bzero (void *to, size_t count); // implemented in memcpy.wat void *memcpy(void *dest, const void * src, size_t n); void *memset(void *mem, int c, size_t n);","title":"string.h"},{"location":"api/api-c-stdlib/#timeh","text":"typedef unsigned long time_t; unsigned long time(unsigned long *time); size_t strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr); size_t strftime_l(char *s, size_t maxsize, const char *format, const struct tm *timeptr, locale_t locale); struct tm *localtime(const time_t *timer); int gettimeofday(struct timeval *tv, void* notused); #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) #define timercmp(tvp,uvp,cmp) \\ ((tvp)->tv_sec cmp (uvp)->tv_sec || \\ ((tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)) #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0","title":"time.h"},{"location":"api/api-c-stdlib/#localeh","text":"#define LC_GLOBAL_LOCALE twr_get_current_locale() char* setlocale(int category, const char* locale); struct lconv *localeconv(void); locale_t newlocale(int category_mask, const char *locale, locale_t base); locale_t uselocale(locale_t); void freelocale(locale_t); locale_t duplocale(locale_t); extern inline locale_t twr_get_current_locale(void);","title":"locale.h"},{"location":"api/api-c-stdlib/#errnoh","text":"typedef int errno_t; extern int * _errno(void); #define errno (*_errno()) errno_t _set_errno(int _Value); errno_t _get_errno(int *_Value);","title":"errno.h"},{"location":"api/api-c-stdlib/#other-include-files-available","text":"float.h limits.h stdbool.h stdint.h","title":"Other include files available"},{"location":"api/api-libc%2B%2B/","text":"libc++ for Web Assembly This section describes twr-wasm's support for using the standard c++ library libc++ with Web Assembly. twr-wasm includes libc++ built for Web Assembly and included in the twr-wasm/lib-c folder. You can build twr-wasm projects in C++ with or without libc++. See the examples tests-libcxx and tests-user for examples of using libc++. See the balls example for how to create a C++ Web Assembly program without the standard C++ library. The primary advantage to this approach is a bit smaller code size. You don't need to staticly link libc++. twr-wasm's libc++ for Web Assembly was built with these build options: LIBCXX_ENABLE_LOCALIZATION=ON LIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON LIBCXXABI_ENABLE_STATIC_UNWINDER=ON LIBCXXABI_ENABLE_STATIC=ON LIBCXX_ENABLE_FILESYSTEM=OFF LIBCXX_ENABLE_TIME_ZONE_DATABASE=OFF LIBCXX_ENABLE_MONOTONIC_CLOCK=OFF LIBCXX_ENABLE_RANDOM_DEVICE=OFF LIBCXX_ENABLE_UNICODE=OFF LIBCXX_ENABLE_WIDE_CHARACTERS=OFF LIBCXX_ENABLE_EXCEPTIONS=OFF LIBCXXABI_ENABLE_EXCEPTIONS=OFF LIBCXX_ENABLE_RTTI=OFF LIBCXX_ENABLE_THREADS=OFF LIBCXXABI_ENABLE_THREADS=OFF LIBCXXABI_HAS_PTHREAD_API=OFF LIBCXX_ENABLE_SHARED=OFF LIBCXXABI_ENABLE_SHARED=OFF","title":"C++ with libc++"},{"location":"api/api-libc%2B%2B/#libc-for-web-assembly","text":"This section describes twr-wasm's support for using the standard c++ library libc++ with Web Assembly. twr-wasm includes libc++ built for Web Assembly and included in the twr-wasm/lib-c folder. You can build twr-wasm projects in C++ with or without libc++. See the examples tests-libcxx and tests-user for examples of using libc++. See the balls example for how to create a C++ Web Assembly program without the standard C++ library. The primary advantage to this approach is a bit smaller code size. You don't need to staticly link libc++. twr-wasm's libc++ for Web Assembly was built with these build options: LIBCXX_ENABLE_LOCALIZATION=ON LIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON LIBCXXABI_ENABLE_STATIC_UNWINDER=ON LIBCXXABI_ENABLE_STATIC=ON LIBCXX_ENABLE_FILESYSTEM=OFF LIBCXX_ENABLE_TIME_ZONE_DATABASE=OFF LIBCXX_ENABLE_MONOTONIC_CLOCK=OFF LIBCXX_ENABLE_RANDOM_DEVICE=OFF LIBCXX_ENABLE_UNICODE=OFF LIBCXX_ENABLE_WIDE_CHARACTERS=OFF LIBCXX_ENABLE_EXCEPTIONS=OFF LIBCXXABI_ENABLE_EXCEPTIONS=OFF LIBCXX_ENABLE_RTTI=OFF LIBCXX_ENABLE_THREADS=OFF LIBCXXABI_ENABLE_THREADS=OFF LIBCXXABI_HAS_PTHREAD_API=OFF LIBCXX_ENABLE_SHARED=OFF LIBCXXABI_ENABLE_SHARED=OFF","title":"libc++ for Web Assembly"},{"location":"api/api-localization/","text":"Locale Support for Web Assembly This section explains twr-wasm's Web Assembly localization support. Character encodings twr-wasm locales supports ASCII, UTF-8 or windows-1252 encoding. UTF-16/32 are not supported as a locale setting, but functions are provided to convert utf-32 (unicode code points) to and from ASCII, UTF-8, and windows-1252 \"code pages\" (there are other miscellaneous utf-32 based functions as well.) UTF-8 uses between one to four bytes to represent any unicode character, with ASCII compatibility in the first 128 bytes. It is also the standard for the web, and the default for clang. But because it uses a variable number of bytes per character it can make string manipulation in C a bit harder than ASCII. Windows-1252 is the default on most Windows computers in many countries - particularly the Americas and western Europe. It is an extension of ASCII that uses a single byte per character. This makes it easier than UTF-8 from a programmers perspective, but it doesn't represent as many characters. It is provided to make it easier to port legacy C code, windows code, as well as a simpler alternative to UTF-8. Although the locale settings don't support utf-32 directly, you can use int arrays (instead of byte arrays) to hold utf-32 strings, and then convert them to/from utf-8 with the help of the provided two functions for this purpose. Locales \"C\" \"C\" is the default locale, as usual. When \"C\" is selected, the functions operate as usual. One subtly is that console i/o functions (such as printf ) will generally function as expected with UTF-8, since the div and window consoles correctly handle UTF-8 character encoding. This is normal on some OSs, such as linux, but not the default on Windows (which often defaults to windows-1252 for backward compatibility). isgraph style functions will only recognize ASCII characters, as is normal. Functions such as strcmp operate on the byte sequence, which will typically results in UTF-8 codes being compared lexically. strcoll will use lexical ordering. \"POSIX\" \"POSIX\" is the same as \"C\" \"\" \"\" is the locale to specify the users default setting (this selects the setting used by the browser). This will also enable UTF-8 in functions such as strcoll . For example, if your browser is set to \"en-US\" as its default locale, setlocale(LC_ALL, \"\") will return en-US.UTF-8 . isgraph style functions will still only recognize ASCII characters (since UTF-8 doesn't encode any single bytes greater than 127). strcoll uses locale specific ordering, and printf will use locale specific decimal points. strcmp still compares two strings lexicographically (byte-by-byte) without considering locale-specific rules, per the spec. \".UTF-8\" \".UTF-8\" is the same as \"\" with twr-wasm. \".1252\" \".1252\" will select the current default locale, but use windows-1252 character encoding (instead of UTF-8). Windows-1252 is a super set of ISO-8859-1 and is the most commonly used encoding for many european languages when unicode is not used. This mode is primarily for legacy software, backwards compatibly, and windows compatibility. 1252 String Literals These days text editors generally default to UTF-8. In order to use windows-1252 source code and/or string literals, such as const char * str=\"\u20ac100\" you may need to: Configure your text editor to save in Windows-1252/ISO-8859-1 format (instead of UTF-8) use compiler flags like --finput-charset and -fexec-charset By default, the Microsoft Visual Studio C compiler (MSVC) does not treat string literals as UTF-8. Instead, it treats them as being encoded in the current code page of the system, which is typically Windows-1252 on western european language Windows systems. twr-wasm is designed to work with clang, which does default to utf-8, so if you are compiling code written for MSVC, and you use extend character sets (non ASCII), you may need to adjust your compiler settings with the flags mentioned above. Others Setting arbitrary locales, such as \"fr-FR\" when the browser is defaulted to another locale, is not supported. Select the default locale To select the user's browser's default locale using the C language, and enable consistent utf-8 support, use a call like this: setlocale(LC_ALL, \"\") libc++ If you are using C++, libc++ locale functions work as expected. C functions The normal standard C library locale support is available, along with some POSIX extensions. In addition, some locale useful twr-wasm specific functions are documented in C API , such as twr_get_current_locale , twr_mbgets , twr_getc32 , twr_utf8_char_len , twr_mbslen_l , twr_utf32_to_code_page , twr_code_page_to_utf32_streamed , twr_get_navlang , twr_localize_numeric_string . Note that io_getc32() , getc(stdin) , fgetc(stdin) do not look at the current locale. iogetc32 returns a 32 bit unicode code point, and getc / fgetc return extended ASCII. For a locale aware character input, use io_mbgetc() or twr_mbgets() . Both use the locale category LC_CTYPE. See C API . Note that when the locale is not set (or whenever the \"C\" locale is set) functions that get character(s) from stdin that are locale aware, like twr_mbgets() , behave different than functions that output characters to stdout (like puts , io_putstr , io_putc , putchar ). Characters to stdout in \"C\" locale will handle UTF-8 characters. For stdin, \"C\" locale uses ASCII. For consistent UTF-8 (or windows-1252) behavior, set the locale as discussed above ( use setlocale ) The primary standard C library locale functions are: char* setlocale(int category, const char* locale); struct lconv *localeconv(void); As well as the standard library functions above, appropriate functions take into account the current locale (printf, strcoll, etc). Note that setlocale returns a string using BCP 47 format (similar to a web browser). Locale strings look like \"en-US.UTF-8\", instead of \"en_US.UTF-8\". A dash, not an underscore, is used as a separator. POSIX functions These are the extended POSIX style functions provided that are related to locale: locale_t newlocale(int category_mask, const char *locale, locale_t base); locale_t uselocale(locale_t); void freelocale(locale_t); locale_t duplocale(locale_t); int isalnum_l(int c, locale_t loc); int isalpha_l(int c, locale_t loc); int isblank_l(int c, locale_t loc); int iscntrl_l(int c, locale_t loc); int isdigit_l(int c, locale_t loc); int isgraph_l(int c, locale_t loc); int islower_l(int c, locale_t loc); int isprint_l(int c, locale_t loc); int ispunct_l(int c, locale_t loc); int isspace_l(int c, locale_t loc); int isupper_l(int c, locale_t loc); int isxdigit_l(int c, locale_t loc); int tolower_l(int c, locale_t loc); int toupper_l(int c, locale_t loc); long long strtoll_l(const char *str, char **str_end, int base, locale_t loc); unsigned long long strtoull_l(const char *str, char **str_end, int base, locale_t loc); float strtof_l(const char *str, char ** str_end, locale_t locale); double strtod_l(const char *str, char **str_end, locale_t locale); long double strtold_l(const char *str, char **str_end, locale_t locale); int strcoll_l(const char* lhs, const char* rhs, locale_t loc); size_t strftime_l(char *s, size_t maxsize, const char *format, const struct tm *timeptr, locale_t locale);","title":"C Localization"},{"location":"api/api-localization/#locale-support-for-web-assembly","text":"This section explains twr-wasm's Web Assembly localization support.","title":"Locale Support for Web Assembly"},{"location":"api/api-localization/#character-encodings","text":"twr-wasm locales supports ASCII, UTF-8 or windows-1252 encoding. UTF-16/32 are not supported as a locale setting, but functions are provided to convert utf-32 (unicode code points) to and from ASCII, UTF-8, and windows-1252 \"code pages\" (there are other miscellaneous utf-32 based functions as well.) UTF-8 uses between one to four bytes to represent any unicode character, with ASCII compatibility in the first 128 bytes. It is also the standard for the web, and the default for clang. But because it uses a variable number of bytes per character it can make string manipulation in C a bit harder than ASCII. Windows-1252 is the default on most Windows computers in many countries - particularly the Americas and western Europe. It is an extension of ASCII that uses a single byte per character. This makes it easier than UTF-8 from a programmers perspective, but it doesn't represent as many characters. It is provided to make it easier to port legacy C code, windows code, as well as a simpler alternative to UTF-8. Although the locale settings don't support utf-32 directly, you can use int arrays (instead of byte arrays) to hold utf-32 strings, and then convert them to/from utf-8 with the help of the provided two functions for this purpose.","title":"Character encodings"},{"location":"api/api-localization/#locales","text":"","title":"Locales"},{"location":"api/api-localization/#c","text":"\"C\" is the default locale, as usual. When \"C\" is selected, the functions operate as usual. One subtly is that console i/o functions (such as printf ) will generally function as expected with UTF-8, since the div and window consoles correctly handle UTF-8 character encoding. This is normal on some OSs, such as linux, but not the default on Windows (which often defaults to windows-1252 for backward compatibility). isgraph style functions will only recognize ASCII characters, as is normal. Functions such as strcmp operate on the byte sequence, which will typically results in UTF-8 codes being compared lexically. strcoll will use lexical ordering.","title":"\"C\""},{"location":"api/api-localization/#posix","text":"\"POSIX\" is the same as \"C\"","title":"\"POSIX\""},{"location":"api/api-localization/#_1","text":"\"\" is the locale to specify the users default setting (this selects the setting used by the browser). This will also enable UTF-8 in functions such as strcoll . For example, if your browser is set to \"en-US\" as its default locale, setlocale(LC_ALL, \"\") will return en-US.UTF-8 . isgraph style functions will still only recognize ASCII characters (since UTF-8 doesn't encode any single bytes greater than 127). strcoll uses locale specific ordering, and printf will use locale specific decimal points. strcmp still compares two strings lexicographically (byte-by-byte) without considering locale-specific rules, per the spec.","title":"\"\""},{"location":"api/api-localization/#utf-8","text":"\".UTF-8\" is the same as \"\" with twr-wasm.","title":"\".UTF-8\""},{"location":"api/api-localization/#1252","text":"\".1252\" will select the current default locale, but use windows-1252 character encoding (instead of UTF-8). Windows-1252 is a super set of ISO-8859-1 and is the most commonly used encoding for many european languages when unicode is not used. This mode is primarily for legacy software, backwards compatibly, and windows compatibility. 1252 String Literals These days text editors generally default to UTF-8. In order to use windows-1252 source code and/or string literals, such as const char * str=\"\u20ac100\" you may need to: Configure your text editor to save in Windows-1252/ISO-8859-1 format (instead of UTF-8) use compiler flags like --finput-charset and -fexec-charset By default, the Microsoft Visual Studio C compiler (MSVC) does not treat string literals as UTF-8. Instead, it treats them as being encoded in the current code page of the system, which is typically Windows-1252 on western european language Windows systems. twr-wasm is designed to work with clang, which does default to utf-8, so if you are compiling code written for MSVC, and you use extend character sets (non ASCII), you may need to adjust your compiler settings with the flags mentioned above.","title":"\".1252\""},{"location":"api/api-localization/#others","text":"Setting arbitrary locales, such as \"fr-FR\" when the browser is defaulted to another locale, is not supported.","title":"Others"},{"location":"api/api-localization/#select-the-default-locale","text":"To select the user's browser's default locale using the C language, and enable consistent utf-8 support, use a call like this: setlocale(LC_ALL, \"\")","title":"Select the default locale"},{"location":"api/api-localization/#libc","text":"If you are using C++, libc++ locale functions work as expected.","title":"libc++"},{"location":"api/api-localization/#c-functions","text":"The normal standard C library locale support is available, along with some POSIX extensions. In addition, some locale useful twr-wasm specific functions are documented in C API , such as twr_get_current_locale , twr_mbgets , twr_getc32 , twr_utf8_char_len , twr_mbslen_l , twr_utf32_to_code_page , twr_code_page_to_utf32_streamed , twr_get_navlang , twr_localize_numeric_string . Note that io_getc32() , getc(stdin) , fgetc(stdin) do not look at the current locale. iogetc32 returns a 32 bit unicode code point, and getc / fgetc return extended ASCII. For a locale aware character input, use io_mbgetc() or twr_mbgets() . Both use the locale category LC_CTYPE. See C API . Note that when the locale is not set (or whenever the \"C\" locale is set) functions that get character(s) from stdin that are locale aware, like twr_mbgets() , behave different than functions that output characters to stdout (like puts , io_putstr , io_putc , putchar ). Characters to stdout in \"C\" locale will handle UTF-8 characters. For stdin, \"C\" locale uses ASCII. For consistent UTF-8 (or windows-1252) behavior, set the locale as discussed above ( use setlocale ) The primary standard C library locale functions are: char* setlocale(int category, const char* locale); struct lconv *localeconv(void); As well as the standard library functions above, appropriate functions take into account the current locale (printf, strcoll, etc). Note that setlocale returns a string using BCP 47 format (similar to a web browser). Locale strings look like \"en-US.UTF-8\", instead of \"en_US.UTF-8\". A dash, not an underscore, is used as a separator.","title":"C functions"},{"location":"api/api-localization/#posix-functions","text":"These are the extended POSIX style functions provided that are related to locale: locale_t newlocale(int category_mask, const char *locale, locale_t base); locale_t uselocale(locale_t); void freelocale(locale_t); locale_t duplocale(locale_t); int isalnum_l(int c, locale_t loc); int isalpha_l(int c, locale_t loc); int isblank_l(int c, locale_t loc); int iscntrl_l(int c, locale_t loc); int isdigit_l(int c, locale_t loc); int isgraph_l(int c, locale_t loc); int islower_l(int c, locale_t loc); int isprint_l(int c, locale_t loc); int ispunct_l(int c, locale_t loc); int isspace_l(int c, locale_t loc); int isupper_l(int c, locale_t loc); int isxdigit_l(int c, locale_t loc); int tolower_l(int c, locale_t loc); int toupper_l(int c, locale_t loc); long long strtoll_l(const char *str, char **str_end, int base, locale_t loc); unsigned long long strtoull_l(const char *str, char **str_end, int base, locale_t loc); float strtof_l(const char *str, char ** str_end, locale_t locale); double strtod_l(const char *str, char **str_end, locale_t locale); long double strtold_l(const char *str, char **str_end, locale_t locale); int strcoll_l(const char* lhs, const char* rhs, locale_t loc); size_t strftime_l(char *s, size_t maxsize, const char *format, const struct tm *timeptr, locale_t locale);","title":"POSIX functions"},{"location":"api/api-typescript/","text":"TypeScript-JavaScript API for WASM This section describes the twr-wasm TypeScript/JavaScript classes that you use to load your wasm modules, and to call C functions in your wasm modules. class twrWasmModule and class twrWasmModuleAsync have similar APIs. The primary difference is that class twrWasmModuleAsync proxies functionality through a Web Worker thread, which allows blocking C functions to be called in your Web Assembly Module. class twrWasmModule import {twrWasmModule} from \"twr-wasm\"; const mod = new twrWasmModule(); twrWasmModule provides the two core JavaScript APIs for access to a Web Assembly Module: loadWasm to load your .wasm module (your compiled C code). callC to call a C function These functions are documented further down in this section. class twrWasmModuleAsync import {twrWasmModuleAsync} from \"twr-wasm\"; const amod = new twrWasmModuleAsync(); twrWasmModuleAsync implements all of the same functions as twrWasmModule , plus allows blocking inputs, and blocking code generally. This is achieved by proxying all the calls through a Web Worker thread. Use twrWasmModuleAsync if your C code blocks, or if you are unsure. If you want better performance and don't need the capabilities of twrWasmModuleAsync , use twrWasmModule . You must use twrWasmModuleAsync in order to: call any blocking C function (meaning it takes \"a long time\") to return use blocking input from a div or canvas ( eg. twr_mbgets ) use twr_sleep See stdio section for information on enabling blocking character input, as well as this Example . When comping/linking your C/C++ code, twrWasmModule and twrWasmModuleAsync use slightly different wasm-ld options since twrWasmModuleAsync uses shared memory. wrWasmModule will operate with shared memory, so technically you could just use the same share memory options with either module, but you don't need the overhead of shared memory when using twrWasmModule, and so better to not enable it. See Compiler Options . twrWasmModuleAsync uses SharedArrayBuffers which require certain HTTP headers to be set. Note that twrWasmModule has an advantage in that it does not use SharedArrayBuffers. Github pages doesn't support the needed CORS headers for SharedArrayBuffers. But other web serving sites do have options to enable the needed CORS headers. For example, the azure static web site config file staticwebapp.config.json looks like this: { \"globalHeaders\": { \"Access-Control-Allow-Origin\": \"*\", \"Cross-Origin-Embedder-Policy\": \"require-corp\", \"Cross-Origin-Opener-Policy\": \"same-origin\" } } server.py in the examples folder will launch a local server with the correct headers. To use Chrome without a web server, see the debugging section . Class Options The twrWasmModule and twrWasmModuleAsync constructor both take optional options. For example: let amod=new twrWasmModuleAsync(); let amod=new twrWasmModuleAsync({ windim:[50,20], forecolor:\"beige\", backcolor:\"DarkOliveGreen\", fontsize:18 }); For a
      it is simpler to set the color and font in the div tag per the normal HTML method. But for
      , that method won't work and you need to use the constructor options for color and fontsize. These are the options: export type TStdioVals=\"div\"|\"canvas\"|\"null\"|\"debug\"; export interface IModOpts { stdio?:TStdioVals, windim?:[number, number], forecolor?:string, backcolor?:string, fontsize?:number, imports?:{}, } stdio You can explicitly set your stdio source (for C/C++ printf, etc) with the stdio option, but typically you don't set it. Instead, it will auto set as described here windim This options is used with a terminal console ( ) to set the width and height, in characters. The canvas width and height, in pixels, will be set based on your fontsize and the width and height (in characters) of the terminal. forecolor and backcolor These can be set to a CSS color (like '#FFFFFF' or 'white') to change the default background and foreground colors. fonsize Changes the default fontsize for div or canvas based I/O. The size is in pixels. loadWasm Use loadWasm to load your compiled C/C++ code (the .wasm file). await mod.loadWasm(\"./mycode.wasm\") callC After your . wasm module is loaded with loadWasm , you call functions in your C/C++ from TypeScript/JavaScript like this: let result=await amod.callC([\"bounce_balls_move\", param1]) If you are calling into C++, you need to use extern \"C\" like this in your C++ code: extern \"C\" int bounce_balls_move() {} Each C/C++ function that you wish to call from TypeScript/JavaScript needs to be exported in your wasm-ld settings like this: --export=bounce_balls_move Or like this in your source file: __attribute__((export_name(\"bounce_balls_move\"))) void bounce_balls_move() { ... See the Compiler Options . callC takes an array where: the first entry is the name of the C function in the wasm module to call and the next entries are a variable number of parameters to pass to the C function, of type: number - will be converted to int32 or float64 as appropriate string - converted to a pointer to module Memory where string is copied into ArrayBuffer - the array is loaded into module memory. If you need to pass the length, pass it as a separate parameter. Any modifications to the memory made by your C code will be reflected back into the JavaScript ArrayBuffer. URL - the url contents are loaded into module Memory, and two C parameters are generated - index (pointer) to the memory, and length callC returns the value returned by the C function that was called. As well int and float , string and structs (or blocks of memory) can be returned. More details can be found in examples/function-calls . The FFT example demonstrates passing a Float32Array view of an ArrayBuffer. Also see Key Concepts . divLog If stdio is set to twr_iodiv , you can use the divLog twrWasmModule/Async function like this: import {twrWasmModule} from \"twr-wasm\"; const mod = new twrWasmModule(); await mod.loadWasm(\"./tests.wasm\"); await mod.callC([\"tests\"]); mod.divLog(\"\\nsin() speed test\"); let sumA=0; const start=Date.now(); for (let i=0; i<2000000;i++) sumA=sumA+Math.sin(i); const endA=Date.now(); let sumB=await mod.callC([\"sin_test\"]); const endB=Date.now(); mod.divLog(\"sum A: \", sumA, \" in ms: \", endA-start); mod.divLog(\"sum B: \", sumB, \" in ms: \", endB-endA); Accessing Data in the Web Assembly Memory You probably will not need to use the twrWasmModule/Async functions in this section, as callC() will convert your parameters for you. But if you return or want to pass in more complicated structs, you might need to. The source in source/twr-wasm-ts/canvas.ts is an example of how these are used. async putString(sin:string, codePage=codePageUTF8) // returns index into WebAssembly.Memory async putU8(u8a:Uint8Array) // returns index into WebAssembly.Memory async putArrayBuffer(ab:ArrayBuffer) // returns index into WebAssembly.Memory async fetchAndPutURL(fnin:URL) // returns index into WebAssembly.Memory async malloc(size:number) // returns index in WebAssembly.Memory. stringToU8(sin:string, codePage=codePageUTF8) copyString(buffer:number, buffer_size:number, sin:string, codePage=codePageUTF8):void getLong(idx:number): number setLong(idx:number, value:number) getDouble(idx:number): number setDouble(idx:number, value:number) getShort(idx:number): number getString(strIndex:number, len?:number, codePage=codePageUTF8): string getU8Arr(idx:number): Uint8Array getU32Arr(idx:number): Uint32Array memory?:WebAssembly.Memory; mem8:Uint8Array; mem32:Uint32Array; memD:Float64Array;","title":"TypeScript/JavaScript"},{"location":"api/api-typescript/#typescript-javascript-api-for-wasm","text":"This section describes the twr-wasm TypeScript/JavaScript classes that you use to load your wasm modules, and to call C functions in your wasm modules. class twrWasmModule and class twrWasmModuleAsync have similar APIs. The primary difference is that class twrWasmModuleAsync proxies functionality through a Web Worker thread, which allows blocking C functions to be called in your Web Assembly Module.","title":"TypeScript-JavaScript API for WASM"},{"location":"api/api-typescript/#class-twrwasmmodule","text":"import {twrWasmModule} from \"twr-wasm\"; const mod = new twrWasmModule(); twrWasmModule provides the two core JavaScript APIs for access to a Web Assembly Module: loadWasm to load your .wasm module (your compiled C code). callC to call a C function These functions are documented further down in this section.","title":"class twrWasmModule"},{"location":"api/api-typescript/#class-twrwasmmoduleasync","text":"import {twrWasmModuleAsync} from \"twr-wasm\"; const amod = new twrWasmModuleAsync(); twrWasmModuleAsync implements all of the same functions as twrWasmModule , plus allows blocking inputs, and blocking code generally. This is achieved by proxying all the calls through a Web Worker thread. Use twrWasmModuleAsync if your C code blocks, or if you are unsure. If you want better performance and don't need the capabilities of twrWasmModuleAsync , use twrWasmModule . You must use twrWasmModuleAsync in order to: call any blocking C function (meaning it takes \"a long time\") to return use blocking input from a div or canvas ( eg. twr_mbgets ) use twr_sleep See stdio section for information on enabling blocking character input, as well as this Example . When comping/linking your C/C++ code, twrWasmModule and twrWasmModuleAsync use slightly different wasm-ld options since twrWasmModuleAsync uses shared memory. wrWasmModule will operate with shared memory, so technically you could just use the same share memory options with either module, but you don't need the overhead of shared memory when using twrWasmModule, and so better to not enable it. See Compiler Options . twrWasmModuleAsync uses SharedArrayBuffers which require certain HTTP headers to be set. Note that twrWasmModule has an advantage in that it does not use SharedArrayBuffers. Github pages doesn't support the needed CORS headers for SharedArrayBuffers. But other web serving sites do have options to enable the needed CORS headers. For example, the azure static web site config file staticwebapp.config.json looks like this: { \"globalHeaders\": { \"Access-Control-Allow-Origin\": \"*\", \"Cross-Origin-Embedder-Policy\": \"require-corp\", \"Cross-Origin-Opener-Policy\": \"same-origin\" } } server.py in the examples folder will launch a local server with the correct headers. To use Chrome without a web server, see the debugging section .","title":"class twrWasmModuleAsync"},{"location":"api/api-typescript/#class-options","text":"The twrWasmModule and twrWasmModuleAsync constructor both take optional options. For example: let amod=new twrWasmModuleAsync(); let amod=new twrWasmModuleAsync({ windim:[50,20], forecolor:\"beige\", backcolor:\"DarkOliveGreen\", fontsize:18 }); For a
      it is simpler to set the color and font in the div tag per the normal HTML method. But for
      , that method won't work and you need to use the constructor options for color and fontsize. These are the options: export type TStdioVals=\"div\"|\"canvas\"|\"null\"|\"debug\"; export interface IModOpts { stdio?:TStdioVals, windim?:[number, number], forecolor?:string, backcolor?:string, fontsize?:number, imports?:{}, }","title":"Class Options"},{"location":"api/api-typescript/#stdio","text":"You can explicitly set your stdio source (for C/C++ printf, etc) with the stdio option, but typically you don't set it. Instead, it will auto set as described here","title":"stdio"},{"location":"api/api-typescript/#windim","text":"This options is used with a terminal console ( ) to set the width and height, in characters. The canvas width and height, in pixels, will be set based on your fontsize and the width and height (in characters) of the terminal.","title":"windim"},{"location":"api/api-typescript/#forecolor-and-backcolor","text":"These can be set to a CSS color (like '#FFFFFF' or 'white') to change the default background and foreground colors.","title":"forecolor and backcolor"},{"location":"api/api-typescript/#fonsize","text":"Changes the default fontsize for div or canvas based I/O. The size is in pixels.","title":"fonsize"},{"location":"api/api-typescript/#loadwasm","text":"Use loadWasm to load your compiled C/C++ code (the .wasm file). await mod.loadWasm(\"./mycode.wasm\")","title":"loadWasm"},{"location":"api/api-typescript/#callc","text":"After your . wasm module is loaded with loadWasm , you call functions in your C/C++ from TypeScript/JavaScript like this: let result=await amod.callC([\"bounce_balls_move\", param1]) If you are calling into C++, you need to use extern \"C\" like this in your C++ code: extern \"C\" int bounce_balls_move() {} Each C/C++ function that you wish to call from TypeScript/JavaScript needs to be exported in your wasm-ld settings like this: --export=bounce_balls_move Or like this in your source file: __attribute__((export_name(\"bounce_balls_move\"))) void bounce_balls_move() { ... See the Compiler Options . callC takes an array where: the first entry is the name of the C function in the wasm module to call and the next entries are a variable number of parameters to pass to the C function, of type: number - will be converted to int32 or float64 as appropriate string - converted to a pointer to module Memory where string is copied into ArrayBuffer - the array is loaded into module memory. If you need to pass the length, pass it as a separate parameter. Any modifications to the memory made by your C code will be reflected back into the JavaScript ArrayBuffer. URL - the url contents are loaded into module Memory, and two C parameters are generated - index (pointer) to the memory, and length callC returns the value returned by the C function that was called. As well int and float , string and structs (or blocks of memory) can be returned. More details can be found in examples/function-calls . The FFT example demonstrates passing a Float32Array view of an ArrayBuffer. Also see Key Concepts .","title":"callC"},{"location":"api/api-typescript/#divlog","text":"If stdio is set to twr_iodiv , you can use the divLog twrWasmModule/Async function like this: import {twrWasmModule} from \"twr-wasm\"; const mod = new twrWasmModule(); await mod.loadWasm(\"./tests.wasm\"); await mod.callC([\"tests\"]); mod.divLog(\"\\nsin() speed test\"); let sumA=0; const start=Date.now(); for (let i=0; i<2000000;i++) sumA=sumA+Math.sin(i); const endA=Date.now(); let sumB=await mod.callC([\"sin_test\"]); const endB=Date.now(); mod.divLog(\"sum A: \", sumA, \" in ms: \", endA-start); mod.divLog(\"sum B: \", sumB, \" in ms: \", endB-endA);","title":"divLog"},{"location":"api/api-typescript/#accessing-data-in-the-web-assembly-memory","text":"You probably will not need to use the twrWasmModule/Async functions in this section, as callC() will convert your parameters for you. But if you return or want to pass in more complicated structs, you might need to. The source in source/twr-wasm-ts/canvas.ts is an example of how these are used. async putString(sin:string, codePage=codePageUTF8) // returns index into WebAssembly.Memory async putU8(u8a:Uint8Array) // returns index into WebAssembly.Memory async putArrayBuffer(ab:ArrayBuffer) // returns index into WebAssembly.Memory async fetchAndPutURL(fnin:URL) // returns index into WebAssembly.Memory async malloc(size:number) // returns index in WebAssembly.Memory. stringToU8(sin:string, codePage=codePageUTF8) copyString(buffer:number, buffer_size:number, sin:string, codePage=codePageUTF8):void getLong(idx:number): number setLong(idx:number, value:number) getDouble(idx:number): number setDouble(idx:number, value:number) getShort(idx:number): number getString(strIndex:number, len?:number, codePage=codePageUTF8): string getU8Arr(idx:number): Uint8Array getU32Arr(idx:number): Uint32Array memory?:WebAssembly.Memory; mem8:Uint8Array; mem32:Uint32Array; memD:Float64Array;","title":"Accessing Data in the Web Assembly Memory"},{"location":"examples/examples-balls/","text":"Bouncing Balls - Web Assembly C++ Example This example uses Web Assembly, C++, and twr-wasm to bounce balls around your HTML page. It uses twr-wasm's 2D Draw API and a C++ Canvas class. View bouncing balls Source for balls The bouncing balls example demonstrates C++ Using the twr-wasm draw 2D APIs that match Javascript Canvas APIs. A C++ wrapper for the JavaScript Canvas class This example does not use libc++, which results in smaller code size. For an example that uses libc++ see tests-libcxx .","title":"balls"},{"location":"examples/examples-fft/","text":"FFT - Web Assembly C Example This example is a demo of integrating an existing FFT C library with Typescript/JavaScript/HTML using Web Assembly. The FFT C library is compiled into a wasm (Web Assembly) module, with the help of twr-wasm. The FFT wasm module is used by the HTML page to calculate the FFT. The FFT input and output is drawn to the web page using the normal JavaScript functions. The FFT library exposes APIs to process data, and doesn't use stdio. The FFT APIs use float32 arrays for complex-number input and output data, and a configuration struct. In the example I generate the input data by adding a 1K and 5K sine waves, call the kiss FFT API to perform the FFT on the generated sine waves, and then graph the input and output data using JavaScript Canvas. View running on the web View Source Code Here is part of the code. The rest can be found in the example. Fast Fourier transform (FFT)
      Input Signal



      FFT Output
      import {twrWasmModule} from \"twr-wasm\"; export async function fftDemo() { const mod=new twrWasmModule(); // load the kiss_fft C code as is, unmodified await mod.loadWasm('kiss_fft.wasm'); // kissFFTData stores and graphs the input and output data // in this example the fft has 1024 bins, and I am using a 48K sampling rate let fft=new kissFFTData(1024, 48000); fft.genSin(1000) fft.addSin(5000) fft.graphIn(\"c-input\"); // see kiss_fft README, but in summary you: (a) alloc config, (b) compute the FFT, (c) free the config // kiss_fft_alloc() returns a malloced structure. Pointers are numbers (index into wasm module memory) in JS land // //kiss_fft_cfg cfg = kiss_fft_alloc( nfft ,is_inverse_fft ,0,0 ); let cfg:number = await mod.callC([\"kiss_fft_alloc\", fft.nfft, 0, 0, 0 ]); // The FFT input and output data are C arrays of complex numbers. // typedef struct { // kiss_fft_scalar r; // kiss_fft_scalar i; // } kiss_fft_cpx; // // /* default is float */ // define kiss_fft_scalar float // So if the FFT data has 1024 bins, then 1024 * 2 floats (r & i) * 4 bytes per float are needed. // I use a JS Float32Array view on the ArrayBuffer to access the floats // When an arrayBuffer is passed in as an argument to mod.callC, // callC will malloc memory in the wasm module of a size that matches the array buffer, then // copy the arraybuffer into the malloc'd memory prior to the function call, // then copy the malloc'd memory contents back into the arrayBuffer post call. // The malloc'd memory is free'd post call. // void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); await mod.callC([\"kiss_fft\", cfg, fft.inArrayBuf, fft.outArrayBuf]); fft.graphOut(\"c-output\"); await mod.callC([\"free\", cfg]); // not much point to this since all the module memory is about to disappear }","title":"fft"},{"location":"examples/examples-helloworld/","text":"Hello World - Web Assembly C Example This example is an very simple twr-wasm program. It uses Web Assembly and C to print \"hello world\" to an HTML
      tag. Also see: Hello World - Step-by-Step C to WASM . View helloworld running live View helloworld Source","title":"hello world"},{"location":"examples/examples-libcxx/","text":"tests-libcxx - Web Assembly libc++ Example This simple smoke test for using libc++ with Web Assembly demonstrates a simple twr-wasm C++ program that uses libc++, and shows the needed makefile. view tests-libcxx running live View tests-libcxx Source Also see this Web Assembly program that uses libc++ with twr-wasm to implement a CLI console. tests-user Live tests-user Source","title":"libc++"},{"location":"examples/examples-maze/","text":"Maze - Web Assembly C Example This example is a port to wasm of a 20 year old Win32 C program with the help of twr-wasm 2D Draw APIs. View live maze here Source for maze This example (in winemu.c) uses the twr-wasm \"d2d\" (Draw 2D) APIs. These allow drawing onto an HTML canvas from C/C++. See the balls example for a C++ Canvas class. I have included the TypesScript below. You can see the C code in the examples/maze folder. This C is interesting in that it is a combination of blocking and non blocking functions. The CalcMaze() function is blocking when the \"slow draw\" flag is set. It uses Sleep() in this case. For this reason, I use twrWasmModuleAsync. The solve section uses repeated calls to SolveStep(), which works well with a JavaScript main loop. I used a javascript interval timer to make repeated calls to the C SolveStep(). If all the C code was structured this way, twrWasmModule could have been used (instead of the Async version) To port this code to twr-wasm I wrote a (very tiny) Win32 compatible API. It only implements the features needed to port maze, but it might be useful to use as a starting point for porting your Win32 code to the web. In the maze example, the two files are winemu.c and winemu.h. You use winemu.h to replace windows.h Maze import {twrWasmModuleAsync} from \"twr-wasm\"; export async function mazeRunner() { const amod=new twrWasmModuleAsync(); await amod.loadWasm('maze.wasm'); //void CalcMaze(HWND hWnd, LONG cell_size, LONG is_black_bg, LONG isd - slow draw) await amod.callC([\"CalcMaze\", 0, 7, 0, 1]); await amod.callC([\"SolveBegin\"]); let timer = setInterval(async ()=>{ let isdone=await amod.callC([\"SolveStep\", 0]); //SolveStep(hwnd)) if (isdone) clearInterval(timer); }, 50); }","title":"maze"},{"location":"examples/examples-more/","text":"More Web Assembly Examples Some other examples include: function-calls demos the different types of parameters that can be passed to a C function tests are the twr-wasm unit tests All Examples Live & Source The source for all of the examples is here on github All of the examples are available to view running live on the internet","title":"more"},{"location":"examples/examples-overview/","text":"Web Assembly C/C++ Examples These C and C++ examples demonstrate how to create different types of Web Assembly (wasm) programs with the twr-wasm library. These are good examples to use as starting points for your own wasm projects. These examples are a good place to learn how to configure clang and wasm-ld to compile and link C/C++ code for use with Web Assembly (wasm). Example Quick Links Click here to view C/C++ Web Assembly twr-wasm examples running live Click here to view source code and make files Examples Overview Each of these examples are designed to illustrate how to use a feature of twr-wasm. Name Description Link helloworld A very simple C wasm example to get you started helloworld stdio-div This simple C program demos inputting and printing characters to a div tag stdio-div stdio-canvas This simple C program demos writing and inputting from a tag that twr-wasm configures as a windowed \"mini-terminal\" stdio-canvas balls These fun Bouncing Balls are written in C++ and demo the 2D drawing APIs with a C++ Canvas wrapper class balls maze This is an old Win32 program ported to wasm and demos the 2D Draw APIs maze fft A demo of calling a C library to perform an FFT that is graphed in Typescript fft tests-libcxx Smoke test for libc++. Shows how to use libc++. tests-libcxx tests-user \"cli\" for tests using libc++ and tests-user more Demo of function calls, units tests more Building the Examples See Example Readme for more information on building and running the examples.","title":"Overview"},{"location":"examples/examples-stdio-canvas/","text":"stdio-canvas - Web Assembly 'terminal' C Example Print and input \"Hello World\" from a \"terminal\" window. A tiny Web Assembly C \"terminal\" can be created with input and output direct to a tag, and you can use it for character I/O with control over where the character appear in the terminal window. This example will move a string up or down in the terminal window when you press the u or d key. View stdio-canvas running live View stdio-canvas Source For another 'terminal' demo View tests-user #include #include #include #include \"twr-crt.h\" #include \"twr-wasm.h\" /* this twr-wasm C example draws a string in the middle of a windowed console, */ /* and allows the user to move the string up or down with the u or d keys */ /* see include/twr-io.h for available functions to draw chars to windowed console */ void show_str_centered(struct IoConsoleWindow* iow, int h, const char* str); void stdio_canvas() { struct IoConsoleWindow* iow=(struct IoConsoleWindow*)twr_get_stdio_con(); if (!(iow->con.header.type&IO_TYPE_WINDOW)) { // could also use assert here twr_conlog(\"error - expected window console\\n\"); return; } int h, c; const char* str=\"Hello World (press u or d)\"; const char* spc=\" \"; h=iow->display.height/2; while (1) { show_str_centered(iow, h, str); c=twr_getc32(); show_str_centered(iow, h, spc); // erase old string if (c=='u') { h=h-1; if (h<0) h=0; } if (c=='d') { h=h+1; if (h>=iow->display.height) h=iow->display.height-1; } } } void show_str_centered(struct IoConsoleWindow* iow, int h, const char* str) { int strlen=strlen(str); int x=(iow->display.width-strlen)/2; io_set_cursorxy(iow, x, h); io_putstr(&iow->con, str); } stdio-canvas example ","title":"stdio-canvas"},{"location":"examples/examples-stdio-div/","text":"stdio-div - Web Assembly stdio-to-div C Example This simple Web Assembly C program demos inputting and printing characters to a div tag. view stdio-div running live View stdio-div Source #include #include #include \"twr-crt.h\" void stdio_div() { char inbuf[64]; int i; printf(\"Square Calculator\\n\"); while (1) { printf(\"Enter an integer: \"); twr_mbgets(inbuf); i=atoi(inbuf); printf(\"%d squared is %d\\n\\n\",i,i*i); } } With an index.html like the following. This time we are using twrWasmModuleAsync which integrates blocking C code into JavaScript. twrWasmModuleAsync can also be used to receive key input from a
      or tag. stdio-div example
      Loading...
      ","title":"stdio-div"},{"location":"gettingstarted/compiler-opts/","text":"Compiling, Linking, and Memory Options This section described how to use clang to compile C/C++ code for Web Assembly, and how to link your files into a .wasm module. twr-wasm lets you use clang directly, without a wrapper. This section describes the needed clang compile options and the wasm-ld link options. You can also take a look at the example makefiles . clang with C When compiling C code with clang for use with wasm and twr-wasm, use these clang options: --target=wasm32 -nostdinc -nostdlib -isystem ../../include -isystem should point to the folder twr-wasm/include . The option line above uses a relative link to include that works if your project is a sub folder in the examples folder. If you installed using npm, then includes are at node_modules/twr-wasm/include (see the installation note on npm ). You will also need to link to twr.a (explained in the linking section below). clang with C++ When compiling C++ code with clang for use with wasm and twr-wasm, use these clang options: --target=wasm32 -fno-exceptions -fno-rtti -nostdlibinc -nostdinc -nostdlib -isystem ../../include You will also need to link to twr.a and libc++.a (explained in the linking section below). Be sure to adjust the path to twr.a , libc++.a , and the include folder as needed (see above note in the C section). linking Use the wasm-ld linker directly with twr-wasm. All of the twr-wasm functions are staticly linked from the library lib-c/twr.a . There is also a version ( lib-c/twrd.a ) of twr-wasm library available with debug symbols. One of these two static libraries should be added to the list of files to link (normally this is twr.a ). Both versions are built with asserts enabled. twr.a is built with -O3 . twrd.a is built with -g -O0 . To use libc++ , link to libc++.a (see the tests-libcxx example makefile). C functions that you wish to call from JavaScript should either have an -export option passed to wasm-ld , or you can use the __attribute__((export_name(\"function_name\"))) option in your C function definition. All exported functions to JavaScript should be C linkage ( extern \"C\" if using C++). wasm-ld should also be passed the following options: If Using twrWasmModule: --no-entry --initial-memory= --max-memory= If Using twrWasmModuleAsync: --no-entry --shared-memory --no-check-features --initial-memory= --max-memory= Memory You set the memory size for your module ( WebAssembly.Memory ) using wasm-ld options as follows (this examples sets your wasm memory to 1MB). The memory size should be a multiple of 64*1024 (64K) chunks. if using twrWasmModule : --initial-memory=1048576 --max-memory=1048576 If you are using twrWasmModuleAsync , shared memory must also be enabled. Like this: --shared-memory --no-check-features --initial-memory=1048576 --max-memory=1048576 See this production note on using shared memory . The memory is an export out of the .wasm into the JavaScript code. There is no support for automatically growing memory. You can change your C/C++ stack size from the default 64K with the following wasm-ld option. This example sets the stack at 128K -z stack-size=131072 You can print your module memory map, heap stats, and stack size using the function from C: void twr_mem_debug_stats(struct IoConsole* outcon); You can call it from Javascript with the output sent to the debug console (stderr) like this: twrWasmModule/Async.callC([\"twr_wasm_print_mem_debug_stats\"]) twrWasmModule and twrWasmModuleAsync expose malloc as an async function, as well as the Web Assembly Module memory as: async malloc(size:number); memory?:WebAssembly.Memory; mem8:Uint8Array; mem32:Uint32Array; memD:Float64Array; to call free() from JavaScript (you probably won't need to), you can use: twrWasmModule/Async.callC(\"twr_free\", index); // index to memory to free, as returned by malloc","title":"Compiler, Linker, Memory"},{"location":"gettingstarted/compiler-opts/#compiling-linking-and-memory-options","text":"This section described how to use clang to compile C/C++ code for Web Assembly, and how to link your files into a .wasm module. twr-wasm lets you use clang directly, without a wrapper. This section describes the needed clang compile options and the wasm-ld link options. You can also take a look at the example makefiles .","title":"Compiling, Linking, and Memory Options"},{"location":"gettingstarted/compiler-opts/#clang-with-c","text":"When compiling C code with clang for use with wasm and twr-wasm, use these clang options: --target=wasm32 -nostdinc -nostdlib -isystem ../../include -isystem should point to the folder twr-wasm/include . The option line above uses a relative link to include that works if your project is a sub folder in the examples folder. If you installed using npm, then includes are at node_modules/twr-wasm/include (see the installation note on npm ). You will also need to link to twr.a (explained in the linking section below).","title":"clang with C"},{"location":"gettingstarted/compiler-opts/#clang-with-c_1","text":"When compiling C++ code with clang for use with wasm and twr-wasm, use these clang options: --target=wasm32 -fno-exceptions -fno-rtti -nostdlibinc -nostdinc -nostdlib -isystem ../../include You will also need to link to twr.a and libc++.a (explained in the linking section below). Be sure to adjust the path to twr.a , libc++.a , and the include folder as needed (see above note in the C section).","title":"clang with C++"},{"location":"gettingstarted/compiler-opts/#linking","text":"Use the wasm-ld linker directly with twr-wasm. All of the twr-wasm functions are staticly linked from the library lib-c/twr.a . There is also a version ( lib-c/twrd.a ) of twr-wasm library available with debug symbols. One of these two static libraries should be added to the list of files to link (normally this is twr.a ). Both versions are built with asserts enabled. twr.a is built with -O3 . twrd.a is built with -g -O0 . To use libc++ , link to libc++.a (see the tests-libcxx example makefile). C functions that you wish to call from JavaScript should either have an -export option passed to wasm-ld , or you can use the __attribute__((export_name(\"function_name\"))) option in your C function definition. All exported functions to JavaScript should be C linkage ( extern \"C\" if using C++). wasm-ld should also be passed the following options: If Using twrWasmModule: --no-entry --initial-memory= --max-memory= If Using twrWasmModuleAsync: --no-entry --shared-memory --no-check-features --initial-memory= --max-memory=","title":"linking"},{"location":"gettingstarted/compiler-opts/#memory","text":"You set the memory size for your module ( WebAssembly.Memory ) using wasm-ld options as follows (this examples sets your wasm memory to 1MB). The memory size should be a multiple of 64*1024 (64K) chunks. if using twrWasmModule : --initial-memory=1048576 --max-memory=1048576 If you are using twrWasmModuleAsync , shared memory must also be enabled. Like this: --shared-memory --no-check-features --initial-memory=1048576 --max-memory=1048576 See this production note on using shared memory . The memory is an export out of the .wasm into the JavaScript code. There is no support for automatically growing memory. You can change your C/C++ stack size from the default 64K with the following wasm-ld option. This example sets the stack at 128K -z stack-size=131072 You can print your module memory map, heap stats, and stack size using the function from C: void twr_mem_debug_stats(struct IoConsole* outcon); You can call it from Javascript with the output sent to the debug console (stderr) like this: twrWasmModule/Async.callC([\"twr_wasm_print_mem_debug_stats\"]) twrWasmModule and twrWasmModuleAsync expose malloc as an async function, as well as the Web Assembly Module memory as: async malloc(size:number); memory?:WebAssembly.Memory; mem8:Uint8Array; mem32:Uint32Array; memD:Float64Array; to call free() from JavaScript (you probably won't need to), you can use: twrWasmModule/Async.callC(\"twr_free\", index); // index to memory to free, as returned by malloc","title":"Memory"},{"location":"gettingstarted/helloworld/","text":"Hello World - Step-by-Step C to WASM This section shows you step by step how to to create a C \"hello world\" program for Web Assembly (WASM) with twr-wasm, C, HTML, and JavaScript. You will learn how to: Create the helloworld.c C file Create the index.html HTML File Compile the helloworld.c code Link the helloworld.o and twr.a files to create a helloworld.wasm file Set the needed library and include paths to allow the twr-wasm libraries to be discovered Create an optional Makefile Execute the \"hello world\" program using a local web server or directly with VS Code and Chrome You can find all of the code for this section in the folder examples\\helloworld . Step 1: Create the C code Create a file helloworld.c #include void hello() { printf(\"hello world\\n\"); } Step 2: Create the HTML Create a file index.html Hello World
      This example uses Import Maps, which are used when not using a bundler like WebPack or Parcel. This can be a simpler and more clear debugging and development environment. The relative path in the importmap section should be updated to point to the location where you installed twr-wasm/lib-js . The path above is correct if your file is in an example subfolder. As another example, if you used git clone https://github.com/twiddlingbits/twr-wasm to create a folder named twr-wasm and you create your hello world project with a folder structure like this: my_project/ \u251c\u2500\u2500 twr-wasm/ \u2514\u2500\u2500 index.html \u2514\u2500\u2500 helloworld.c \u2514\u2500\u2500 helloworld.wasm Then you would use an Import Map code snippet like this: Step 3: Compile your C code to create your .wasm file clang --target=wasm32 -nostdinc -nostdlib -isystem ../../include -c helloworld.c -o helloworld.o wasm-ld helloworld.o ../../lib-c/twr.a -o helloworld.wasm --no-entry --initial-memory=131072 --max-memory=131072 --export=hello The path to twr.a and to include may need to be updated to match your installation. The above path is correct if your code is in an example subfolder. Alternately, if you had the folder structure described in Step 2: my_project/ \u251c\u2500\u2500 twr-wasm/ \u2514\u2500\u2500 index.html \u2514\u2500\u2500 helloworld.c \u2514\u2500\u2500 helloworld.wasm \u2514\u2500\u2500 Makefile You could use a MakeFile like this: CC := clang TWRCFLAGS := --target=wasm32 -nostdinc -nostdlib -isystem twr-wasm/include CFLAGS := -c -Wall -O3 $(TWRCFLAGS) CFLAGS_DEBUG := -c -Wall -g -O0 $(TWRCFLAGS) .PHONY: default default: helloworld.wasm helloworld.o: helloworld.c $(CC) $(CFLAGS) $< -o $@ helloworld.wasm: helloworld.o wasm-ld helloworld.o twr-wasm/lib-c/twr.a -o helloworld.wasm \\ --no-entry --initial-memory=131072 --max-memory=131072 \\ --export=hello Step 4: Load your web page The two easiest ways to load and execute your index.html web page locally are: Option A: Run a local web Server You can run a local server to view your helloworld program. Copy the file server.py from the examples folder to your project folder where your index.html resides. Execute with the shell command python server.py . Option B: VS Code launch.json Alternately, you can launch chrome without a local web server. Add an entry similar to the following to your VS code project's .vscode\\launch.json . Adjust the file and cwd lines to be correct for your project. { \"name\": \"hello\", \"type\": \"chrome\", \"request\": \"launch\", \"runtimeArgs\": [ \"--allow-file-access-from-files\", \"--autoplay-policy=no-user-gesture-required\", \"--enable-features=SharedArrayBuffer\" ], \"file\": \"${workspaceFolder}/examples/index.html\", \"cwd\": \"${workspaceFolder}/examples/\" } --autoplay-policy=no-user-gesture-required and --enable-features=SharedArrayBuffer are not required for this simple \"hello world\" example, but will be needed if you request user input or you are using twrWasModuleAsync. See live version Here is a link to the helloworld function running in the twiddlingbits.dev site. Next steps after hello world A good way to get your own code up and running is to copy one of the twr-wasm/examples , get it to build and run, then start modifying it. The example makefiles prove a more practical way to configure and execute clang and wasm-ld. \"Hello World\" uses the twr-wasm class twrWasmModule . If you wish to use C blocking functions, such as twr_getc32 or twr_sleep , you can use twrWasmModuleAsync . This square calculator example shows how to do this. If you wish to build an app that makes non-block calls into C, the balls example shows how to do this. The maze example uses a combination of blocking and non-blocking C functions.","title":"Create wasm C Hello World"},{"location":"gettingstarted/helloworld/#hello-world-step-by-step-c-to-wasm","text":"This section shows you step by step how to to create a C \"hello world\" program for Web Assembly (WASM) with twr-wasm, C, HTML, and JavaScript. You will learn how to: Create the helloworld.c C file Create the index.html HTML File Compile the helloworld.c code Link the helloworld.o and twr.a files to create a helloworld.wasm file Set the needed library and include paths to allow the twr-wasm libraries to be discovered Create an optional Makefile Execute the \"hello world\" program using a local web server or directly with VS Code and Chrome You can find all of the code for this section in the folder examples\\helloworld .","title":"Hello World - Step-by-Step C to WASM"},{"location":"gettingstarted/helloworld/#step-1-create-the-c-code","text":"Create a file helloworld.c #include void hello() { printf(\"hello world\\n\"); }","title":"Step 1: Create the C code"},{"location":"gettingstarted/helloworld/#step-2-create-the-html","text":"Create a file index.html Hello World
      This example uses Import Maps, which are used when not using a bundler like WebPack or Parcel. This can be a simpler and more clear debugging and development environment. The relative path in the importmap section should be updated to point to the location where you installed twr-wasm/lib-js . The path above is correct if your file is in an example subfolder. As another example, if you used git clone https://github.com/twiddlingbits/twr-wasm to create a folder named twr-wasm and you create your hello world project with a folder structure like this: my_project/ \u251c\u2500\u2500 twr-wasm/ \u2514\u2500\u2500 index.html \u2514\u2500\u2500 helloworld.c \u2514\u2500\u2500 helloworld.wasm Then you would use an Import Map code snippet like this: ","title":"Step 2: Create the HTML"},{"location":"gettingstarted/helloworld/#step-3-compile-your-c-code-to-create-your-wasm-file","text":"clang --target=wasm32 -nostdinc -nostdlib -isystem ../../include -c helloworld.c -o helloworld.o wasm-ld helloworld.o ../../lib-c/twr.a -o helloworld.wasm --no-entry --initial-memory=131072 --max-memory=131072 --export=hello The path to twr.a and to include may need to be updated to match your installation. The above path is correct if your code is in an example subfolder. Alternately, if you had the folder structure described in Step 2: my_project/ \u251c\u2500\u2500 twr-wasm/ \u2514\u2500\u2500 index.html \u2514\u2500\u2500 helloworld.c \u2514\u2500\u2500 helloworld.wasm \u2514\u2500\u2500 Makefile You could use a MakeFile like this: CC := clang TWRCFLAGS := --target=wasm32 -nostdinc -nostdlib -isystem twr-wasm/include CFLAGS := -c -Wall -O3 $(TWRCFLAGS) CFLAGS_DEBUG := -c -Wall -g -O0 $(TWRCFLAGS) .PHONY: default default: helloworld.wasm helloworld.o: helloworld.c $(CC) $(CFLAGS) $< -o $@ helloworld.wasm: helloworld.o wasm-ld helloworld.o twr-wasm/lib-c/twr.a -o helloworld.wasm \\ --no-entry --initial-memory=131072 --max-memory=131072 \\ --export=hello","title":"Step 3: Compile your C code to create your .wasm file"},{"location":"gettingstarted/helloworld/#step-4-load-your-web-page","text":"The two easiest ways to load and execute your index.html web page locally are:","title":"Step 4: Load your web page"},{"location":"gettingstarted/helloworld/#option-a-run-a-local-web-server","text":"You can run a local server to view your helloworld program. Copy the file server.py from the examples folder to your project folder where your index.html resides. Execute with the shell command python server.py .","title":"Option A: Run a local web Server"},{"location":"gettingstarted/helloworld/#option-b-vs-code-launchjson","text":"Alternately, you can launch chrome without a local web server. Add an entry similar to the following to your VS code project's .vscode\\launch.json . Adjust the file and cwd lines to be correct for your project. { \"name\": \"hello\", \"type\": \"chrome\", \"request\": \"launch\", \"runtimeArgs\": [ \"--allow-file-access-from-files\", \"--autoplay-policy=no-user-gesture-required\", \"--enable-features=SharedArrayBuffer\" ], \"file\": \"${workspaceFolder}/examples/index.html\", \"cwd\": \"${workspaceFolder}/examples/\" } --autoplay-policy=no-user-gesture-required and --enable-features=SharedArrayBuffer are not required for this simple \"hello world\" example, but will be needed if you request user input or you are using twrWasModuleAsync.","title":"Option B: VS Code launch.json"},{"location":"gettingstarted/helloworld/#see-live-version","text":"Here is a link to the helloworld function running in the twiddlingbits.dev site.","title":"See live version"},{"location":"gettingstarted/helloworld/#next-steps-after-hello-world","text":"A good way to get your own code up and running is to copy one of the twr-wasm/examples , get it to build and run, then start modifying it. The example makefiles prove a more practical way to configure and execute clang and wasm-ld. \"Hello World\" uses the twr-wasm class twrWasmModule . If you wish to use C blocking functions, such as twr_getc32 or twr_sleep , you can use twrWasmModuleAsync . This square calculator example shows how to do this. If you wish to build an app that makes non-block calls into C, the balls example shows how to do this. The maze example uses a combination of blocking and non-blocking C functions.","title":"Next steps after hello world"},{"location":"gettingstarted/installation/","text":"Installing twr-wasm This section describes how to install twr-wasm on your computer so that you can compile and link C/C++ to Web Assembly (WASM). npm install twr-wasm or git clone https://github.com/twiddlingbits/twr-wasm npm install will install everything necessary to build your software: built libraries (lib-js, lib-c), include. In addition the examples are installed. git clone will copy the built libraries (lib-js, lib-c), include, as well as the source, examples, doc source and VS Code settings. Either will work, although with different pros and cons -- see the below notes. After installation, Using twr-wasm can be a bit more complicated than using a package that is all JavaScript because your applications need to use twr-wasm JavaScript and C libraries. Installs for your C/C++ code To build C/C++ code for use in your wasm project, you will need to install clang and the wasm-ld linker. If you are using Windows, more details can be found at the end of the Building Source section. A Note on npm install After installation from npm, you will have a folder structure like this: node_modules\\ twr-wasm\\ examples\\ include\\ lib-c\\ lib-js\\ LICENSE package.json readme.md The JavaScript and TypeScript exports are in lib-js and should be found by VS Code, TypeScript or your bundler as usual when using a statement like import {twrWasmModule} from \"twr-wasm\" . The C library ( twr.a ) that you will need to link your C/C++ program to is found in the libs-c folder, and the C/C++ include files that you will need to use in your C/C++ program are found in the include folder. You will need to use paths to to these folders in your make file . All of the examples (in the examples folder above) have make files that use a relative path for twr.a and includes . These paths will work fine if your code is in an examples sub-folder as a peer to the other examples. But assuming your code is in your own project folder elsewhere, you will need to determine the correct path to twr.a and includes from your project's make file. Details on how to do this can be found in the leter sections: Hello World walkthrough and the Compiler and Linker Options section . There is no real downside to this installation method, except possibly: (1) it does not include source code (use git clone for that), and (b) the C libraries are buried inside your node_modules. A Note on git clone install This method of installation installs the complete code base, including source and build binaries. The primary downside to this method is that the JavaScript side of twr-wasm will not be placed in a node_modules folder. This will likely make it difficult for a bundler, TypeScript or VS Code to find the location of imports. There are a few solutions to this. In the provided hello world example, I use a package.json file with an alias entry. This syntax is supported by the Parcel bundler: { \"@parcel/resolver-default\": { \"packageExports\": true }, \"alias\": { \"twr-wasm\": \"../../lib-js/index.js\" }, \"dependencies\": { \"twr-wasm\": \"^2.0.0\" } } In the FFT example, I use the paths entry in the tsconfig.json file. This is found by TypeScript, VS Code and the Parcel bundler. \"paths\": { \"twr-wasm\": [\"./../../lib-js/index\"] } The paths for alias and paths shown above are correct for the included examples, but will likely need to be adjust for your project (see the following section \"Your First C Web Assembly Program\" ) As a alternative, you could install with both npm and git .","title":"Installation"},{"location":"gettingstarted/keyconcepts/","text":"Key Concepts - C/C++ WASM This section describes some key concepts that apply when using twr-wasm with your C/C++ Web Assembly code. Overview Your C/C++ Web Assembly project will consist of HTML (and related JavaScript or Typescript) and C or C++ source files that are compiled into a \".wasm\" binary file that is loaded as a Web Assembly module by your JavaScript or HTML. You will call C functions (or C++ with ' extern \"C\" ' linkage) in the .wasm module from your JavaScript. You can also call JavaScript functions from your C/C++ code, but this is less common. There is no direct equivalent to a C \"main\". Instead, a wasm module provides exported C functions that you can call from JavaScript/TypeScript. A wasm module is more like a runtime loaded dynamic library. On the JavaScript side you will use the twr-wasm JavaScript/TypeScript class twrWasmModule or twrWasmModuleAsync to load the .wasm module, and then call C functions in it (more details are in the TypeScript/Javascript API section ). You're C/C++ code can be non-blocking or blocking. Blocking means that it \"takes a long time\" to return. For example, if you want to send mouse events to C code, have the code process them then return, this would be non-blocking. Alternately, if your C code is a big loop that never returns, that would be very blocking. You can use the twr-wasm class twrWasmModuleAsync to execute blocking code from JavaScript. The example maze demonstrates both non-blocking and blocking C calls. Here are some examples of different types of C/C++ code: If you're C/C++ code does not have any direct user interface built in, it can do its calculations and return. The FFT is an example of this. If your C/C++ code uses a classic C \"UI\", where it gets keys from stdin and sends the results to stdout, you can direct stdin and stdout to a
      or tag. This is explained in the stdio section. Your C/C++ code could be sent events from JavaScript (such mouse, key, timer, or other). This is done by simply calling a C function with the events as parameters. The C/C++ code could then generate no output, could render to a
      or using stdio type C/C++ functions, or it could render to a using 2D drawing APIs that correspond to JavaScript canvas 2D draw operations. ( Balls ) is an example. Steps to integrate C code with JavaScript code Here are the general steps to integrate your C with your JavaScript: Compile your C code with clang and link with wasm-ld to create the .wasm file. On the JavaScript side you: Access twr-wasm \"ES\" modules in the normal way with import . Add a
      or to your HTML ( see stdio ) Use new twrWasmModule() , followed by a call to loadWasm() , then one or more callC() . Alternately, use twrWasmModuleAsync() -- which is interchangeable with twrWasmModule, but proxies through a worker thread, and adds blocking support, including blocking char input. Passing strings, arrayBuffers, etc The Web Assembly runtime provided in a browser will only pass numbers between C functions and JavaScript functions. This means if you use twrWasmModule.callC to call a C function, and pass integers or floats as arguments, they will work as expected. But if you pass a string, arrayBuffer, or the contents or a URL, twrWasmModule.callC will: allocate memory in your WebAssembly.Memory (using malloc). copy the string (or arrayBuffer or URL contents) into this memory. pass the memory index (aka a pointer in C land) to your C code. If URL contents are passed, your C function will receive a pointer to the data as the first argument, and a length as the second argument. If an arrayBuffer is passed to your C/C++ code, you probably will also need to pass in the length (unless it is already known). Upon return, the malloced memory is freed, and if the argument was an arrayBuffer, the appropriate contents in the wasm module memory are copied back into the arrayBuffer. This means that if your C code modifies a passed in block of arrayBuffer memory, the results will be reflected back into javaScript land. Some module functions (such as getString ) take or return an \"index:number\". Here index means an index into WebAssembly.Memory. As far as your C code is concerned, this is a pointer. Recalled that an arrayBuffer can be created and accessed using classes like Uint8Array or Float32Array . It is helpful to look at the examples .","title":"Key Concepts"},{"location":"gettingstarted/stdio/","text":"Stdio with C/C++ Web Assembly This section describes how you can direct C/C++ standard input or output to or from a div or canvas tag in a twr-wasm C/C++ wasm project. Use div or canvas tag Standard input and output can be directed to a
      or to a HTML tag. A
      is used for streamed character input and output, and a is used for sending characters or simple graphics to windowed input and output. In the windowed mode, the position of characters in a \"terminal\" style window can be specified. In windowed mode, you can use functions that output to stdout or input from stdin, as well as functions that use x,y coordinates, colors, etc.
      will be used for stdin and stdout if found. will be used for stdin and stdout if it exists and no div found. if neither of the above
      or is defined in your HTML, then stdout is sent to the debug console in your browser. And stdin is not available. If you use twrWasmModule options, a fourth null options is available. Unicode characters and symbols are supported in stdout and stdin and windowed i/o (see localization ). The window console also supports chunky (low res) graphics (each character cell can be used as a 2x3 graphic array). stderr streams to the browser's debug console. Examples Name View Live Link Source Link stdin and stdout to
      View square demo Source simple \"terminal\" via View hello world demo Source \"cli\" with a stdio View CLI demo using libc++ Source IO Console Docs stdin , stdout , and stderr are abstracted by a twr-wasm IO Consoles . UTF-8 or Windows-1252 Stdin and stdout can support UTF-8 or Windows-1252 character encodings (see localization ) stdout or stderr #include to access stdout , stdin , stderr , and FILE . FILE is supported for user input and output, and for stderr. File i/o (to a filesystem) is not currently supported. You can use these functions to output to the standard library defines stderr or stdout : fputc, putc, vfprintf, fprintf, fwrite You can use the IO Console functions referenced above to send to stdout and stderr . These functions go to stdout: printf, vprintf, puts, putchar Note that when characters are sent to the browser console using stderr they will not render to the console until a newline, return, or ASCII 03 (End-of-Text) is sent. For example: #include fprintf(stderr, \"hello over there in browser debug console land\\n\"); A more common method to send output to the debug console is to use twr_conlog . See General C API Section . stdin You can get characters from the standard C define stdin with these functions: io_mbgets - get a multibyte string from a console using the current locale character encoding twr_mbgets - similar to io_mbgets , except always gets a multibyte locale format string from stdin. io_mbgetc - get a multibyte character from an IoConsole (like stdin ) using the current locale character encoding getc (sames as fgetc ) - get a single byte from a FILE * (IoConsole) -- returning ASCII or extended ASCII (window-1252 encoding) io_getc32 - gets a 32 bit unicode code point from an IoConsole (which currently needs to be stdin) Reading from stdin is blocking, and so twrWasmModuleAsync must be used to receive keys from stdin. JavaScript needed for char input You should add a line like the following to your JavaScript for stdin to work: for twr_iodiv document.getElementById(\"twr_iodiv\").addEventListener(\"keydown\",(ev)=>{amod.keyDownDiv(ev)}); for twr_iocanvas document.getElementById(\"twr_iocanvas\").addEventListener(\"keydown\",(ev)=>{amod.keyDownCanvas(ev)}); You likely want a line like this to set the focus to the div or canvas so the user doesn't have to click on it: document.getElementById(\"twr_iocanvas\").focus(); You will also need to set the tabindex attribute in your div tag like this:
      See the stdio-div and stdio-canvas examples. Note that this section describes blocking input using stdin. As an alternative, you can send events (keyboard, mouse, timer, etc) to a non-blocking C function from JavaScript using callC . See the balls example.","title":"Stdio"},{"location":"more/building/","text":"Building the Source Source for twr-wasm The source can be found at: https://github.com/twiddlingbits/twr-wasm The main branch contains the latest release. The dev branch is work in progress. Tools needed You will need these core tools: NPM - package manager Typescript clang tool chain - for C/C++ code wasm-ld - to link the .wasm files wat2wasm - to compile web assembly (.wat) files of which I have a few GNU make git - to clone twr-wasm source, or to clone llvm, if you want to build libc++ In addition, you might need: VS Code - to use the debug launcher and build tasks Parcel v2 - to bundle the examples mkdocs - to build the documentation static web site python - mkdocs is built with python, and you need python to run server.py in examples CMake and ninja - to build llvm libc++ There is a deprecated gcc build that I used to use for testing, but now the tests are executed in wasm. To Build the Libraries (lib-c, lib-js) cd source make or on windows cd source mingw32-make To Build the Examples See examples/readme.md for more information. To build the examples, but not bundle them. cd examples sh buildall.sh To build bundles: sh buildbundles.sh To Build the docs In twr-wasm root folder: mkdocs build The destination of the build is found in the mkdocs.yml file ( site_dir: azure/docsite/ ). Usually the docs are built as part of building the static web site that hosts the docs and examples. This is accomplished using this shell script (found in examples folder): buildazure.sh To Build libc++ for wasm and twr-wasm See the instructions in the comments in the shell script source\\libcxx\\buildlibcxx.sh Installing clang and wasm-ld on Windows Here is how I installed the tools for windows: install MSYS2 1. https://www.msys2.org/ 2. After the install completes, run UCRT64 terminal by clicking on the MSYS2 UCRT64 in the Start menu 3. pacman -Syuu install gcc using MSYS2 UCRT64 1. Use MSYS2 UCRT64 terminal (per above) 1. pacman -S mingw-w64-ucrt-x86_64-toolchain install clang and wasm-ld using MSYS2 UCRT64 2. Use MSYS2 UCRT64 (per above) 1. pacman -S mingw-w64-ucrt-x86_64-clang 2. pacman -S mingw-w64-x86_64-lld update PATH env variable using the windows control panel (search for path) 2. added C:\\msys64\\ucrt64\\bin 3. added C:\\msys64\\mingw64\\bin 4. added C:\\msys64\\usr\\bin (for sh.exe used by mingw32-make) wabt tools: can be found here https://github.com/WebAssembly/wabt/releases","title":"Building the Source"},{"location":"more/debugging/","text":"Debugging This section describes some tips for debugging your Web Assembly (asm) program. Debug & Release libs There are release (twr.a) and debug (twrd.a) versions of the twr-wasm C library. See the examples for use of both. The \"debug\" version has debug symbols enabled and is built with -O0 . The \"release\" version has no debug symbols and optimization is set to -O3 . Both have asserts enabled. In general, you should use the \"release\" version unless you wish to step through the twr-wasm source -- in which case use the \"debug\" version. libc++.a is not built with debug symbols. C/C++ Source Level Debugging In order to enable C/C++ source debugging with wasm and clang, do the following: Use Chrome Install the Chrome extension: C/C++ DevTools Support (DWARF) ( https://chromewebstore.google.com/detail/pdcpmagijalfljmkmjngeonclgbbannb ) Use the clang compile flag -g to add debug annotation to your object files You will may want to turn off optimization to allow the debugger to have a bit more logical behavior (remove the -O flag or set to -O0) You may want to use the version of the twr-wasm C library that has debug symbols enabled (twrd.a). Only if you want to step into the twrd.a source. You need to serve your files with a (likely local) web server. For example, 'python server.py' is provided. 'server.py' can be found in the examples root folder. Note that your local server needs to enable SharedArrayBuffers -- see the server.py example. your code can be bundled or unbundled, but you need to ensure that the web server/browser can find the source code also see Example Readme Useful Functions Use twr_conlog to print 'printf' style to the JavaScript console from C (reference is elsewhere in this doc.) #include \"twr-wasm.h\" twr_conlog(\"hello 99 in hex: %x\",99); Use twrWasmModule.divLog() to print to a div inside JavaScript code (reference is elsewhere in this doc.) Testing Without a Web Server Note: If you use this technique, you will not be able to get the c/C++ DevTool chrome extension to run, and so source level debugging won't work. You can execute and debug JavaScript with wasm from local files without an HTTP server. It might be helpful to download the twr-wasm source code from github when you do this (so you can step through the twr-wasm typescript code as needed). See the examples and Example Readme for more detail on how this works. In general, you will need to add a clip of code similar to this to your HTML: Make sure the paths are correct. You will need to set the following flags when running chrome from the shell (the first is only strictly required if using twrWasmModuleAsync): --enable-features=SharedArrayBuffer --allow-file-access-from-files You can create a launch.json entry similar to this: { \"name\": \"Examples\", \"type\": \"chrome\", \"request\": \"launch\", \"runtimeArgs\": [\"--allow-file-access-from-files\",\"--autoplay-policy=no-user-gesture-required\",\"--enable-features=SharedArrayBuffer\"], \"file\": \"${workspaceFolder}/examples/index.html\", \"cwd\": \"${workspaceFolder}/examples/\" }","title":"Debugging WASM"},{"location":"more/production/","text":"Production Important Production Note twr-wasm class twrWasmModuleAsync uses SharedArrayBuffers, and there are special CORS headers needed for these, that are not widely enabled by default on web servers. server.py or staticwebapp.config.json shows which headers to set (also see the SharedArrayBuffer documentation online).","title":"Production"},{"location":"more/wasm-problem/","text":"WASM Runtime Limitations HTML browsers can load a Web Assembly module, and execute it's bytecode in a browser virtual machine. You compile your code using clang with the target code format being web assembly (wasm) byte code. There are a few issues that one immediately encounters trying to execute code that is more complicated than squaring a number. The first is that there is no C/C++ runtime support native to a Web Assembly module. That is, no malloc or printf or similar functions. Even beyond than that, there are missing compiler support functions. That is, clang code generation will produce calls for compiler support routines needed for floating point, memcpy, and the like. This code is usually handled behind the scenes for you. For example, gcc will link to \"libgcc\" automatically. clang uses \"compile-rt\". This doesn't happen with Web Assembly compiles (unless you use emscripten or twr-wasm). The second problem is that all the function calls between your wasm module and your javascript are limited to parameters and return values that are numbers (integer and float). No strings, arrays, struct pointers, etc. The third problem is that legacy C code or games often block, and when written this way they don't naturally integrate with the JavaScript asynchronous programming model. twr-wasm is a static C library (twr.a) that you can link to your clang C/C++ code, as well as a set of JavaScript/Typescript modules that solve these issues.","title":"WASM Runtime Limitations"}]} \ No newline at end of file +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"twr-wasm - Easy C/C++ Web Assembly Modules Documentation for twr-wasm Version 2.1.0 twr-wasm is a simple, lightweight and easy to use library for building C/C++ Web Assembly code directly with clang. It solves some common use cases with less work than the more feature rich emscripten. twr-wasm is easy to understand, and has some cool features. You can input and print streaming character i/o to a
      tag, use a element as an ANSI terminal, or use a C/C++ 2D drawing api (that is compatible with JavaScript Canvas APIs) to draw to a element. You can run blocking C/C++. twr-wasm allows you to run C/C++ code in a web browser. Legacy code, libraries, full applications, or single functions can be integrated with JavaScript and Typescript. twr-wasm is designed to be used with the standard llvm clang compiler and tools. twr-wasm was previously named tiny-wasm-runtime. View C++ Web Assembly Bouncing Ball Demo View bouncing balls here Key Features compile and link C/C++ for use with web assembly using clang directly standard C library, libc++. and purpose built APIs available from C/C++ TypeScrpt/JavaScript classes to load WASM modules and call C/C++ functions localization support, UTF-8, and windows-1252 support in C/C++, print and get characters to/from
      tags in your HTML page in C/C++, print and get characters to/from a based \"terminal\" in C/C++ use 2D drawing API compatible with JavaScript Canvas in C/C++, use the \"blocking loop\" pattern and integrate with Javascript's asynchronous event loop Why? WASM Runtime Limitations section explains why a library like twr-wasm is needed to use Web Assembly. Hello World Here is the simplest twr-wasm example. C code: #include void hello() { printf(\"hello world\\n\"); } index.html: Hello World
      View Live Web Assembly Demos Name View Live Link Source Link Bouncing Balls (C++) View bouncing balls Source for balls Maze (Win32 C Port) View live maze Source for maze Input from
      View square demo Source Mini-Terminal (hello world using ) View demo Source Mini-Terminal (\"cli\" using libc++ and ) View console Source On Github https://github.com/twiddlingbits/twr-wasm Version 2 vs. 1 libc++ built for Web Assembly is included most of the standard C library is now implemented instructions for Web Assembly C/C++ source level debugging version of library with debug symbols provided locale, UTF-8, and windows-1252 support Version 2 Limitations libc++ not built with exceptions enabled some standard C library functions are not 100% implemented Designed to work with a browser. Not tested with or designed to work with node.js Not all of compile-rt is ported (but most bits you need are) The following non-compatible changes since 1.0 (relatively minor) there is no longer 'twr_' prefixed std c lib functions (use the normal std c lib names) most 'twr_wasm_' prefixed functions have been shortened to 'twr_'. some functions were renamed or changed slightly to be more consistent, but no functionality is lost. Post Feedback Please post feedback (it worked for you, didn't work, requests, questions, etc) at https://github.com/twiddlingbits/twr-wasm/","title":"Home"},{"location":"#twr-wasm-easy-cc-web-assembly-modules","text":"Documentation for twr-wasm Version 2.1.0 twr-wasm is a simple, lightweight and easy to use library for building C/C++ Web Assembly code directly with clang. It solves some common use cases with less work than the more feature rich emscripten. twr-wasm is easy to understand, and has some cool features. You can input and print streaming character i/o to a
      tag, use a element as an ANSI terminal, or use a C/C++ 2D drawing api (that is compatible with JavaScript Canvas APIs) to draw to a element. You can run blocking C/C++. twr-wasm allows you to run C/C++ code in a web browser. Legacy code, libraries, full applications, or single functions can be integrated with JavaScript and Typescript. twr-wasm is designed to be used with the standard llvm clang compiler and tools. twr-wasm was previously named tiny-wasm-runtime.","title":"twr-wasm - Easy C/C++ Web Assembly Modules"},{"location":"#view-c-web-assembly-bouncing-ball-demo","text":"View bouncing balls here","title":"View C++ Web Assembly Bouncing Ball Demo"},{"location":"#key-features","text":"compile and link C/C++ for use with web assembly using clang directly standard C library, libc++. and purpose built APIs available from C/C++ TypeScrpt/JavaScript classes to load WASM modules and call C/C++ functions localization support, UTF-8, and windows-1252 support in C/C++, print and get characters to/from
      tags in your HTML page in C/C++, print and get characters to/from a based \"terminal\" in C/C++ use 2D drawing API compatible with JavaScript Canvas in C/C++, use the \"blocking loop\" pattern and integrate with Javascript's asynchronous event loop","title":"Key Features"},{"location":"#why","text":"WASM Runtime Limitations section explains why a library like twr-wasm is needed to use Web Assembly.","title":"Why?"},{"location":"#hello-world","text":"Here is the simplest twr-wasm example. C code: #include void hello() { printf(\"hello world\\n\"); } index.html: Hello World
      ","title":"Hello World"},{"location":"#view-live-web-assembly-demos","text":"Name View Live Link Source Link Bouncing Balls (C++) View bouncing balls Source for balls Maze (Win32 C Port) View live maze Source for maze Input from
      View square demo Source Mini-Terminal (hello world using ) View demo Source Mini-Terminal (\"cli\" using libc++ and ) View console Source","title":"View Live Web Assembly Demos"},{"location":"#on-github","text":"https://github.com/twiddlingbits/twr-wasm","title":"On Github"},{"location":"#version-2-vs-1","text":"libc++ built for Web Assembly is included most of the standard C library is now implemented instructions for Web Assembly C/C++ source level debugging version of library with debug symbols provided locale, UTF-8, and windows-1252 support","title":"Version 2 vs. 1"},{"location":"#version-2-limitations","text":"libc++ not built with exceptions enabled some standard C library functions are not 100% implemented Designed to work with a browser. Not tested with or designed to work with node.js Not all of compile-rt is ported (but most bits you need are) The following non-compatible changes since 1.0 (relatively minor) there is no longer 'twr_' prefixed std c lib functions (use the normal std c lib names) most 'twr_wasm_' prefixed functions have been shortened to 'twr_'. some functions were renamed or changed slightly to be more consistent, but no functionality is lost.","title":"Version 2 Limitations"},{"location":"#post-feedback","text":"Please post feedback (it worked for you, didn't work, requests, questions, etc) at https://github.com/twiddlingbits/twr-wasm/","title":"Post Feedback"},{"location":"api/api-c-con/","text":"Console C API for Web Assembly (Streamed and Windowed) This section describes twr-wasm's method of providing and abstracting console I/O in Web Assembly Modules. C character based input/output is abstracted by struct IoConsole . Consoles can be \"tty\" aka \"streamed\", or they can be \"windowed\" (aka a \"terminal\"). Also see stdio Examples Name View Live Link Source Link \"terminal\" in/out with a View mini-term demo Source Getting stderr,stdin, stdout stdio.h defines stdin , stdout , stderr as explained here: stdio stdio.h also defines FILE like this: typedef struct IoConsole FILE; from : #define stderr (FILE *)(twr_get_stderr_con()) #define stdin (FILE *)(twr_get_stdio_con()) #define stdout (FILE *)(twr_get_stdio_con()) Getting a new console stdin and stdout are set as explaind here . However, in unusual cases you might want to access the various consoles directly, regardless of how stdin, stdout, or stderr are set. You can do so like this: io_nullcon Returns an IoConsole that goes to the bit bucket. io_getc32 will return 0. #include \"twr-io.h\" struct IoConsole* io_nullcon(void); twr_debugcon Returns an IoConsole that goes to the browser's debug console. #include \"twr-crt.h\" struct IoConsole* twr_debugcon(void); twr_divcon Returns an IoConsole that goes to
      , if it exists. #include \"twr-crt.h\" struct IoConsole* twr_divcon(void); twr_windowcon Returns an IoConsole that goes to , if it exists. NOTE: Only one call can be made to this function, and it is usually made by the twr-wasm C runtime, so you likely won't call this function. #include \"twr-crt.h\" struct IoConsole* twr_windowcon(void); IO Console Functions io_putc Sends a byte to an IoConsole and supports the current locale's character encoding. This function will \"stream\" using the current code page. In other words, if you io_putc ASCII, it will work as \"normal\". If the current locale is set to 1252, then you can send windows-1252 encoded characters. If the current locale is UTF-8, then you can stream UTF-8 (that is, call io_putc once for each byte of the multi-byte UTF-8 character). Note that when characters are sent to the browser console using stderr they will not render to the console until a newline, return, or ASCII 03 (End-of-Text) is sent. #include \"twr-io.h\" void io_putc(struct IoConsole* io, unsigned char c); io_putstr Calls io_putc for each byte in the passed string. #include \"twr-io.h\" void io_putstr(struct IoConsole* io, const char* s); io_printf Identical to fprintf , however io_printf will call io_begin_draw and io_end_draw around its drawing activities -- resulting in snapper performance. For example: #include \"twr-io.h\" io_printf(twr_debugcon(), \"hello over there in browser debug console land\\n\"); or #include #include io_printf(stdout, \"hello world\\n\"); #include void io_printf(struct IoConsole *io, const char *format, ...); io_getc32 Waits for the user to enter and then returns a unicode code point. Currently only really works with an IoConsole that is stdin. To return characters encoded with the current locale, see io_mbgetc #include int io_getc32(struct IoConsole* io); io_mbgetc io_mbgetc will get a character from stdin and encode it using the character encoding of the LC_CTYPE category of the current locale. \"C\" will use ASCII. UTF-8 and windows-1252 are also supported. #include void io_mbgetc(struct IoConsole* io, char* strout); io_mbgets Gets a string from an IoConsole (which needs to be stdin). Returns when the user presses \"Enter\". Displays a cursor character and echos the inputted characters, at the current cursor position. Uses character encoding of LC_TYPE of current locale. #include char *io_mbgets(struct IoConsole* io, char *buffer ); io_get_cursor Returns an integer of the current cursor position. The cursor is where the next io_putc is going to go. For windowed consoles, the cursor position ranges from [0, width*height-1], inclusive. #include int io_get_cursor(struct IoConsole* io); io_set_colors For windowed consoles only. Sets a 24 bit RGB default color for the foreground and background. The prior default colors are changed (lost). For example, if you set the default colors when you created the window (see stdio ), the defaults will no longer be active. Use io_get_colors to save existing colors for later restoration using io_set_colors . A call to io_set_colors doesn't actually cause any on screen changes. Instead, these new default colors are used in future draw and text calls. A foreground and background color is set for each cell in the console window. The cell's colors are set to these default foreground/background colors when a call to io_setc , io_setreset , etc is made. #include void io_set_colors(struct IoConsole* io, unsigned long foreground, unsigned long background); io_get_colors For windowed consoles only. Gets the current default colors. #include void io_get_colors(struct IoConsole* io, unsigned long *foreground, unsigned long *background); io_cls For windowed consoles only. Clears the screen. That is, all character cells in the window are set to a space, their colors are reset to the current default colors (see io_set_colors ). #include void io_cls(struct IoConsoleWindow* iow); io_setc For windowed consoles only. Sets a window cell to a character. Sends a byte to an IoConsole and supports the current locale's character encoding. This function will \"stream\" using the current code page. In other words, if you io_setc ASCII, it will work as \"normal\". If the current locale is set to 1252, then you can send windows-1252 encoded characters. If the current locale is UTF-8, then you can stream UTF-8 (that is, call io_setc once for each byte of the multi-byte UTF-8 character). #include bool io_setc(struct IoConsoleWindow* iow, int location, unsigned char c); io_setc32 For windowed consoles only. Sets a window cell to a unicode code point. The colors are set to the defaults (see io_set_colors ). #include void io_setc32(struct IoConsoleWindow* iow, int location, int c); io_setreset For windowed consoles only. Sets or resets (clears) a chunky graphics \"pixel\". Each character cell can also be a 2x3 grid of graphic \"pixels\". In other words, the terminal window has pixel dimensions of width 2 x height 3. The color will be set to the defaults if the impacted cell is not a graphics cell. If it is an existing graphics cell, the colors don't change. See the stdio-canvas example. #include bool io_setreset(struct IoConsoleWindow* iow, int x, int y, bool isset); io_point For windowed consoles only. Checks if a chunky graphics \"pixel\" is set or clear. See io_setreset . #include bool io_point(struct IoConsoleWindow* iow, int x, int y); io_set_cursor Moves the cursor. See io_get_cursor . #include void io_set_cursor(struct IoConsoleWindow* iow, int loc); io_begin_draw For windowed consoles only. This call (and its matching io_end_draw) are not required. But if you bracket any call sequence that draws to the terminal window with an io_begin_draw and io_end_draw , the updates will be batched into one update. io_begin_draw can be nested. This will increase performance and usually prevents the user from seeing partial updates. See the terminal-window io_canvas example. #include void io_begin_draw(struct IoConsole* io); io_end_draw For windowed consoles only. See io_begin_draw . #include void io_end_draw(struct IoConsole* io);","title":"C Console I/O"},{"location":"api/api-c-con/#console-c-api-for-web-assembly-streamed-and-windowed","text":"This section describes twr-wasm's method of providing and abstracting console I/O in Web Assembly Modules. C character based input/output is abstracted by struct IoConsole . Consoles can be \"tty\" aka \"streamed\", or they can be \"windowed\" (aka a \"terminal\"). Also see stdio","title":"Console C API for Web Assembly (Streamed and Windowed)"},{"location":"api/api-c-con/#examples","text":"Name View Live Link Source Link \"terminal\" in/out with a View mini-term demo Source","title":"Examples"},{"location":"api/api-c-con/#getting-stderrstdin-stdout","text":"stdio.h defines stdin , stdout , stderr as explained here: stdio stdio.h also defines FILE like this: typedef struct IoConsole FILE; from : #define stderr (FILE *)(twr_get_stderr_con()) #define stdin (FILE *)(twr_get_stdio_con()) #define stdout (FILE *)(twr_get_stdio_con())","title":"Getting stderr,stdin, stdout"},{"location":"api/api-c-con/#getting-a-new-console","text":"stdin and stdout are set as explaind here . However, in unusual cases you might want to access the various consoles directly, regardless of how stdin, stdout, or stderr are set. You can do so like this:","title":"Getting a new console"},{"location":"api/api-c-con/#io_nullcon","text":"Returns an IoConsole that goes to the bit bucket. io_getc32 will return 0. #include \"twr-io.h\" struct IoConsole* io_nullcon(void);","title":"io_nullcon"},{"location":"api/api-c-con/#twr_debugcon","text":"Returns an IoConsole that goes to the browser's debug console. #include \"twr-crt.h\" struct IoConsole* twr_debugcon(void);","title":"twr_debugcon"},{"location":"api/api-c-con/#twr_divcon","text":"Returns an IoConsole that goes to
      , if it exists. #include \"twr-crt.h\" struct IoConsole* twr_divcon(void);","title":"twr_divcon"},{"location":"api/api-c-con/#twr_windowcon","text":"Returns an IoConsole that goes to , if it exists. NOTE: Only one call can be made to this function, and it is usually made by the twr-wasm C runtime, so you likely won't call this function. #include \"twr-crt.h\" struct IoConsole* twr_windowcon(void);","title":"twr_windowcon"},{"location":"api/api-c-con/#io-console-functions","text":"","title":"IO Console Functions"},{"location":"api/api-c-con/#io_putc","text":"Sends a byte to an IoConsole and supports the current locale's character encoding. This function will \"stream\" using the current code page. In other words, if you io_putc ASCII, it will work as \"normal\". If the current locale is set to 1252, then you can send windows-1252 encoded characters. If the current locale is UTF-8, then you can stream UTF-8 (that is, call io_putc once for each byte of the multi-byte UTF-8 character). Note that when characters are sent to the browser console using stderr they will not render to the console until a newline, return, or ASCII 03 (End-of-Text) is sent. #include \"twr-io.h\" void io_putc(struct IoConsole* io, unsigned char c);","title":"io_putc"},{"location":"api/api-c-con/#io_putstr","text":"Calls io_putc for each byte in the passed string. #include \"twr-io.h\" void io_putstr(struct IoConsole* io, const char* s);","title":"io_putstr"},{"location":"api/api-c-con/#io_printf","text":"Identical to fprintf , however io_printf will call io_begin_draw and io_end_draw around its drawing activities -- resulting in snapper performance. For example: #include \"twr-io.h\" io_printf(twr_debugcon(), \"hello over there in browser debug console land\\n\"); or #include #include io_printf(stdout, \"hello world\\n\"); #include void io_printf(struct IoConsole *io, const char *format, ...);","title":"io_printf"},{"location":"api/api-c-con/#io_getc32","text":"Waits for the user to enter and then returns a unicode code point. Currently only really works with an IoConsole that is stdin. To return characters encoded with the current locale, see io_mbgetc #include int io_getc32(struct IoConsole* io);","title":"io_getc32"},{"location":"api/api-c-con/#io_mbgetc","text":"io_mbgetc will get a character from stdin and encode it using the character encoding of the LC_CTYPE category of the current locale. \"C\" will use ASCII. UTF-8 and windows-1252 are also supported. #include void io_mbgetc(struct IoConsole* io, char* strout);","title":"io_mbgetc"},{"location":"api/api-c-con/#io_mbgets","text":"Gets a string from an IoConsole (which needs to be stdin). Returns when the user presses \"Enter\". Displays a cursor character and echos the inputted characters, at the current cursor position. Uses character encoding of LC_TYPE of current locale. #include char *io_mbgets(struct IoConsole* io, char *buffer );","title":"io_mbgets"},{"location":"api/api-c-con/#io_get_cursor","text":"Returns an integer of the current cursor position. The cursor is where the next io_putc is going to go. For windowed consoles, the cursor position ranges from [0, width*height-1], inclusive. #include int io_get_cursor(struct IoConsole* io);","title":"io_get_cursor"},{"location":"api/api-c-con/#io_set_colors","text":"For windowed consoles only. Sets a 24 bit RGB default color for the foreground and background. The prior default colors are changed (lost). For example, if you set the default colors when you created the window (see stdio ), the defaults will no longer be active. Use io_get_colors to save existing colors for later restoration using io_set_colors . A call to io_set_colors doesn't actually cause any on screen changes. Instead, these new default colors are used in future draw and text calls. A foreground and background color is set for each cell in the console window. The cell's colors are set to these default foreground/background colors when a call to io_setc , io_setreset , etc is made. #include void io_set_colors(struct IoConsole* io, unsigned long foreground, unsigned long background);","title":"io_set_colors"},{"location":"api/api-c-con/#io_get_colors","text":"For windowed consoles only. Gets the current default colors. #include void io_get_colors(struct IoConsole* io, unsigned long *foreground, unsigned long *background);","title":"io_get_colors"},{"location":"api/api-c-con/#io_cls","text":"For windowed consoles only. Clears the screen. That is, all character cells in the window are set to a space, their colors are reset to the current default colors (see io_set_colors ). #include void io_cls(struct IoConsoleWindow* iow);","title":"io_cls"},{"location":"api/api-c-con/#io_setc","text":"For windowed consoles only. Sets a window cell to a character. Sends a byte to an IoConsole and supports the current locale's character encoding. This function will \"stream\" using the current code page. In other words, if you io_setc ASCII, it will work as \"normal\". If the current locale is set to 1252, then you can send windows-1252 encoded characters. If the current locale is UTF-8, then you can stream UTF-8 (that is, call io_setc once for each byte of the multi-byte UTF-8 character). #include bool io_setc(struct IoConsoleWindow* iow, int location, unsigned char c);","title":"io_setc"},{"location":"api/api-c-con/#io_setc32","text":"For windowed consoles only. Sets a window cell to a unicode code point. The colors are set to the defaults (see io_set_colors ). #include void io_setc32(struct IoConsoleWindow* iow, int location, int c);","title":"io_setc32"},{"location":"api/api-c-con/#io_setreset","text":"For windowed consoles only. Sets or resets (clears) a chunky graphics \"pixel\". Each character cell can also be a 2x3 grid of graphic \"pixels\". In other words, the terminal window has pixel dimensions of width 2 x height 3. The color will be set to the defaults if the impacted cell is not a graphics cell. If it is an existing graphics cell, the colors don't change. See the stdio-canvas example. #include bool io_setreset(struct IoConsoleWindow* iow, int x, int y, bool isset);","title":"io_setreset"},{"location":"api/api-c-con/#io_point","text":"For windowed consoles only. Checks if a chunky graphics \"pixel\" is set or clear. See io_setreset . #include bool io_point(struct IoConsoleWindow* iow, int x, int y);","title":"io_point"},{"location":"api/api-c-con/#io_set_cursor","text":"Moves the cursor. See io_get_cursor . #include void io_set_cursor(struct IoConsoleWindow* iow, int loc);","title":"io_set_cursor"},{"location":"api/api-c-con/#io_begin_draw","text":"For windowed consoles only. This call (and its matching io_end_draw) are not required. But if you bracket any call sequence that draws to the terminal window with an io_begin_draw and io_end_draw , the updates will be batched into one update. io_begin_draw can be nested. This will increase performance and usually prevents the user from seeing partial updates. See the terminal-window io_canvas example. #include void io_begin_draw(struct IoConsole* io);","title":"io_begin_draw"},{"location":"api/api-c-con/#io_end_draw","text":"For windowed consoles only. See io_begin_draw . #include void io_end_draw(struct IoConsole* io);","title":"io_end_draw"},{"location":"api/api-c-d2d/","text":"2D Draw C API for Web Assembly This section describes twr-wasm's C D2D API, which allows your Web Assembly module to call many of the JavaScript Canvas APIs. There is also a C++ canvas wrapper class in the balls example. Examples Name View Live Link Source Link Bouncing Balls (C++) View bouncing balls Source for balls Maze (Win32 C Port) View live maze here Source for maze Overview Add a canvas tag to your HTML named twr_d2dcanvas like this example (you can use any width/height you like): To draw using the C API: - call d2d_start_draw_sequence() - call draw commands, like d2d_fillrect() - call d2d_end_draw_sequence() Commands are queued until flush'd, which will take the batch of queued draw cmds, and execute them. In the case of twrWasmModuleAsync, the batch of commands is sent over to the JavaScript main thread for execution. By batching the calls, performance is improved. Flush() waits for the commands to finish execution before returning. Flush() is called automatically by d2d_end_draw_sequence(). You pass an argument to d2d_start_draw_sequence() specifying how many instructions will trigger an automatic flush. You can make this larger for efficiency, or smaller if you want to see the render progress with more frequently. There is no limit on the size of the queue, except memory used in the wasm module. There is a flush() function that you can manually call, but it is not normally needed, unless you would like to ensure a sequence renders before d2d_end_draw_sequence() is called, or before the count passed d2d_start_draw_sequence() is met. If you are using twrWasmModuleAsync, or if you are re-rendering the entire frame for each animation update, you should ensure that all of your draws for a single complete frame are made without a call to flush() in the middle of the draw operations, as this may cause flashing. Functions These are the Canvas APIs currently available in C: struct d2d_draw_seq* d2d_start_draw_sequence(int flush_at_ins_count); void d2d_end_draw_sequence(struct d2d_draw_seq* ds); void d2d_flush(struct d2d_draw_seq* ds); int d2d_get_canvas_prop(const char* prop); void d2d_fillrect(struct d2d_draw_seq* ds, double x, double y, double w, double h); void d2d_strokerect(struct d2d_draw_seq* ds, double x, double y, double w, double h); void d2d_filltext(struct d2d_draw_seq* ds, const char* str, double x, double y); void d2d_fillcodepoint(struct d2d_draw_seq* ds, char c, double x, double y); void d2d_measuretext(struct d2d_draw_seq* ds, const char* str, struct d2d_text_metrics *tm); void d2d_save(struct d2d_draw_seq* ds); void d2d_restore(struct d2d_draw_seq* ds); void d2d_setlinewidth(struct d2d_draw_seq* ds, double width); void d2d_setfillstylergba(struct d2d_draw_seq* ds, unsigned long color); void d2d_setstrokestylergba(struct d2d_draw_seq* ds, unsigned long color); void d2d_setfillstyle(struct d2d_draw_seq* ds, const char* css_color); void d2d_setstrokestyle(struct d2d_draw_seq* ds, const char* css_color); void d2d_setfont(struct d2d_draw_seq* ds, const char* font); void d2d_createlineargradient(struct d2d_draw_seq* ds, long id, double x0, double y0, double x1, double y1); void d2d_createradialgradient(struct d2d_draw_seq* ds, long id, double x0, double y0, double radius0, double x1, double y1, double radius1); void d2d_addcolorstop(struct d2d_draw_seq* ds, long gradID, long position, const char* csscolor); void d2d_setfillstylegradient(struct d2d_draw_seq* ds, long gradID); void d2d_releaseid(struct d2d_draw_seq* ds, long id); void d2d_beginpath(struct d2d_draw_seq* ds); void d2d_fill(struct d2d_draw_seq* ds); void d2d_stroke(struct d2d_draw_seq* ds); void d2d_moveto(struct d2d_draw_seq* ds, double x, double y); void d2d_lineto(struct d2d_draw_seq* ds, double x, double y); void d2d_arc(struct d2d_draw_seq* ds, double x, double y, double radius, double start_angle, double end_angle, bool counterclockwise); void d2d_bezierto(struct d2d_draw_seq* ds, double cp1x, double cp1y, double cp2x, double cp2y, double x, double y); void d2d_imagedata(struct d2d_draw_seq* ds, long id, void* mem, unsigned long length, unsigned long width, unsigned long height); void d2d_putimagedata(struct d2d_draw_seq* ds, long id, unsigned long dx, unsigned long dy); void d2d_putimagedatadirty(struct d2d_draw_seq* ds, long id, unsigned long dx, unsigned long dy, unsigned long dirtyX, unsigned long dirtyY, unsigned long dirtyWidth, unsigned long dirtyHeight); d2d_measuretext() returns this structure: struct d2d_text_metrics { double actualBoundingBoxAscent; double actualBoundingBoxDescent; double actualBoundingBoxLeft; double actualBoundingBoxRight; double fontBoundingBoxAscent; double fontBoundingBoxDescent; double width; }; d2d_get_canvas_prop() returns a value of: export interface ICanvasProps { charWidth: number, charHeight: number, foreColor: number, backColor: number, widthInChars: number, heightInChars: number, canvasWidth:number, canvasHeight:number }","title":"C Draw 2D"},{"location":"api/api-c-d2d/#2d-draw-c-api-for-web-assembly","text":"This section describes twr-wasm's C D2D API, which allows your Web Assembly module to call many of the JavaScript Canvas APIs. There is also a C++ canvas wrapper class in the balls example.","title":"2D Draw C API for Web Assembly"},{"location":"api/api-c-d2d/#examples","text":"Name View Live Link Source Link Bouncing Balls (C++) View bouncing balls Source for balls Maze (Win32 C Port) View live maze here Source for maze","title":"Examples"},{"location":"api/api-c-d2d/#overview","text":"Add a canvas tag to your HTML named twr_d2dcanvas like this example (you can use any width/height you like): To draw using the C API: - call d2d_start_draw_sequence() - call draw commands, like d2d_fillrect() - call d2d_end_draw_sequence() Commands are queued until flush'd, which will take the batch of queued draw cmds, and execute them. In the case of twrWasmModuleAsync, the batch of commands is sent over to the JavaScript main thread for execution. By batching the calls, performance is improved. Flush() waits for the commands to finish execution before returning. Flush() is called automatically by d2d_end_draw_sequence(). You pass an argument to d2d_start_draw_sequence() specifying how many instructions will trigger an automatic flush. You can make this larger for efficiency, or smaller if you want to see the render progress with more frequently. There is no limit on the size of the queue, except memory used in the wasm module. There is a flush() function that you can manually call, but it is not normally needed, unless you would like to ensure a sequence renders before d2d_end_draw_sequence() is called, or before the count passed d2d_start_draw_sequence() is met. If you are using twrWasmModuleAsync, or if you are re-rendering the entire frame for each animation update, you should ensure that all of your draws for a single complete frame are made without a call to flush() in the middle of the draw operations, as this may cause flashing.","title":"Overview"},{"location":"api/api-c-d2d/#functions","text":"These are the Canvas APIs currently available in C: struct d2d_draw_seq* d2d_start_draw_sequence(int flush_at_ins_count); void d2d_end_draw_sequence(struct d2d_draw_seq* ds); void d2d_flush(struct d2d_draw_seq* ds); int d2d_get_canvas_prop(const char* prop); void d2d_fillrect(struct d2d_draw_seq* ds, double x, double y, double w, double h); void d2d_strokerect(struct d2d_draw_seq* ds, double x, double y, double w, double h); void d2d_filltext(struct d2d_draw_seq* ds, const char* str, double x, double y); void d2d_fillcodepoint(struct d2d_draw_seq* ds, char c, double x, double y); void d2d_measuretext(struct d2d_draw_seq* ds, const char* str, struct d2d_text_metrics *tm); void d2d_save(struct d2d_draw_seq* ds); void d2d_restore(struct d2d_draw_seq* ds); void d2d_setlinewidth(struct d2d_draw_seq* ds, double width); void d2d_setfillstylergba(struct d2d_draw_seq* ds, unsigned long color); void d2d_setstrokestylergba(struct d2d_draw_seq* ds, unsigned long color); void d2d_setfillstyle(struct d2d_draw_seq* ds, const char* css_color); void d2d_setstrokestyle(struct d2d_draw_seq* ds, const char* css_color); void d2d_setfont(struct d2d_draw_seq* ds, const char* font); void d2d_createlineargradient(struct d2d_draw_seq* ds, long id, double x0, double y0, double x1, double y1); void d2d_createradialgradient(struct d2d_draw_seq* ds, long id, double x0, double y0, double radius0, double x1, double y1, double radius1); void d2d_addcolorstop(struct d2d_draw_seq* ds, long gradID, long position, const char* csscolor); void d2d_setfillstylegradient(struct d2d_draw_seq* ds, long gradID); void d2d_releaseid(struct d2d_draw_seq* ds, long id); void d2d_beginpath(struct d2d_draw_seq* ds); void d2d_fill(struct d2d_draw_seq* ds); void d2d_stroke(struct d2d_draw_seq* ds); void d2d_moveto(struct d2d_draw_seq* ds, double x, double y); void d2d_lineto(struct d2d_draw_seq* ds, double x, double y); void d2d_arc(struct d2d_draw_seq* ds, double x, double y, double radius, double start_angle, double end_angle, bool counterclockwise); void d2d_bezierto(struct d2d_draw_seq* ds, double cp1x, double cp1y, double cp2x, double cp2y, double x, double y); void d2d_imagedata(struct d2d_draw_seq* ds, long id, void* mem, unsigned long length, unsigned long width, unsigned long height); void d2d_putimagedata(struct d2d_draw_seq* ds, long id, unsigned long dx, unsigned long dy); void d2d_putimagedatadirty(struct d2d_draw_seq* ds, long id, unsigned long dx, unsigned long dy, unsigned long dirtyX, unsigned long dirtyY, unsigned long dirtyWidth, unsigned long dirtyHeight); d2d_measuretext() returns this structure: struct d2d_text_metrics { double actualBoundingBoxAscent; double actualBoundingBoxDescent; double actualBoundingBoxLeft; double actualBoundingBoxRight; double fontBoundingBoxAscent; double fontBoundingBoxDescent; double width; }; d2d_get_canvas_prop() returns a value of: export interface ICanvasProps { charWidth: number, charHeight: number, foreColor: number, backColor: number, widthInChars: number, heightInChars: number, canvasWidth:number, canvasHeight:number }","title":"Functions"},{"location":"api/api-c-general/","text":"General C API for WASM Overview This sections describes the \"general\" twr-wasm functions available that don't fit neatly into another category (such as standard C library functions, Draw 2D functions, etc.) These functions often start with \"twr_\" and are generally found in this include file: \\twr-wasm\\include\\twr-crt.h bzero Set a block of memory to zeros. Calls memset(to, 0, count) . #include void bzero (void *to, size_t count); getc This is the standard c library function (see the the standard library docs available on the internet). Of note this function will return extended ASCII (128-255 inclusive). The extend ASCII are always encoded with Windows-1252 encoding. See twr_getc32 for a list of related functions. Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input. twr_atod Similar to stdlib atof . #include \"twr-crt.h\" double twr_atod(const char* str); twr_atou64 Convert a string to a 64 bit unsigned integer, stopping when the first non-valid character is encountered. If len is provided, it will be set to the number of characters read. Radix should be >=2 and <=36 -- for example, 10 is a normal base 10 number and 16 is hexadecimal. #include \"twr-crt.h\" int64_t twr_atou64(const char *str, int* len, int radix); twr_dtoa The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed #include \"twr-crt.h\" void twr_dtoa(char* buffer, int sizeInBytes, double value, int max_precision); twr_cache_malloc/free These functions keep allocated memory in a cache for much faster re-access than the standard malloc/free. #include \"twr-crt.h\" void *twr_cache_malloc(twr_size_t size); void twr_cache_free(void* mem); twr_code_page_to_utf32_streamed Return a unicode code point (aka utf-32 value) when passed a byte stream that represents an encoded character using the current local's LC_CTYPE code page. A zero is returned if the byte stream has not yet completed a decode. For example: int cp setlocale(LC_ALL, \"\"); // set to default locale, which will be UTF-8 encoding with local language/region // turn a UTF-8 Euro into a UTF-32 value cp==twr_code_page_to_utf32_streamed(0xE2); assert (cp==0); cp=twr_code_page_to_utf32_streamed(0x82); assert (cp==0); cp=twr_code_page_to_utf32_streamed(0xAC); assert (cp==0x000020AC); // Euro Code points #include int twr_code_page_to_utf32_streamed(unsigned char byte) twr_conlog twr_conlog prints debug messages to the browser console from your C code. #include \"twr-crt.h\" void twr_conlog(char* format, ...); Each call to twr_conlog() will generate a single call to console.log() in JavaScript to ensure that you see debug prints. This call is identical to printf, except that it adds a newline. The current implementation does not wait for the debug string to output to the console before returning from twr_conlog, when using twrWasmModuleAsync. In this case, it can take a small bit of time for the string to make its way across the Worker Thread boundary. This is normally not a problem and results in faster performance. But if your code crashes soon after the debug print, the print might not appear. If you think this is an issue, you can call twr_sleep(1) after your twr_conlog call. This will force a blocking wait for the print to print. Prior to 1.0, this function was called twr_dbg_printf , and operated slightly differently. twr_epoch_timems Returns the number of milliseconds since the start of the epoch. #include \"twr-wasm.h\" uint64_t twr_epoch_timems(); twr_getc32 Gets a 32 bit unicode code point character from stdin . Unlike the standard C library function getchar , twr_getc32 does not buffer a line (that is, twr_getc32 will return a character before the user presses Enter). twr_getc32 is implemented as: int twr_getc32() { return io_getc32(twr_get_stdio_con()); } Note that stdlib getchar and ungetc are not currently implemented. Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input. Also see: io_mbgets - get a multibyte string from a console using the current locale character encoding twr_mbgets - similar to io_mbgets , except always gets a multibyte locale format string from stdin. io_mbgetc - get a multibyte character from an IoConsole (like stdin ) using the current locale character encoding getc (sames as fgetc ) - get a single byte from a FILE * (IoConsole) -- returning ASCII or extended ASCII (window-1252 encoding) io_getc32 - gets a 32 bit unicode code point from an IoConsole (which currently needs to be stdin) #include \"twr-crt.h\" int twr_getc32(); twr_get_navlang Returns the BCP 47 language tag as found in javacript navigator.language . If len is not null, it will be filled in with the string length of the language tag. #include \"twr-crt.h\" const char* twr_get_navlang(int *len); twr_get_current_locale extern inline locale_t twr_get_current_locale(void); twr_get_current_locale will return the locale that has been set by setlocale . It can be used to pass to a function that takes a locale_t. twr_localize_numeric_string Functions like twr_dtoa do not localize the decimal point. To get a localized decimal point, you can use printf , or alternately twr_localize_numeric_string to post process a string. For example: char b[10]; strcpy(b, \"1.23\"); twr_localize_numeric_string(b, twr_get_current_locale()); // if locale was set to french, then b is now 1,23 #include void twr_localize_numeric_string(char* str, locale_t locale); twr_mem_debug_stats Print memory map and malloc stats to stderr or stdout. (note FILE * is the same as struct IoConsole*) #include void twr_mem_debug_stats(struct IoConsole* outcon); twr_mbgets Gets a string from stdin . The string will be in the current locale's character encoding -- ASCII for \"C\", and either UTF-8 or windows-1252 for \"\". See localization . #include \"twr-crt.h\" char* twr_mbgets(char* buffer); Internally this function uses the stdio IoConsole -- see the IoConsole section for more advanced input/output. This function will encode characters as specified by the LC_CTYPE category of the current locale. ASCII is used for \"C\", and UTF-8 and Windows-1252 are also supported (see localization ) Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input. twr_mbslen_l Returns the number of characters in a string using the character encoding of the passed locale (ASCII for \"C\", UTF-8, or windows-1252 for \"\"). You can use twr_get_current_locale to find the current locale. #include size_t twr_mbslen_l(const char *str, locale_t locale); twr_sleep twr_sleep is a traditional blocking sleep function. This function is blocking, and you must use twrWasmModuleAsync. #include \"twr-wasm.h\" void twr_sleep(int ms); twr_tofixed This function is identical to its JavaScript version. #include \"twr-wasm.h\" void twr_tofixed(char* buffer, int buffer_size, double value, int dec_digits); The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed twr_toexponential This function is identical to its JavaScript version. #include \"twr-wasm.h\" void twr_toexponential(char* buffer, int buffer_size, double value, int dec_digits); The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed twr_strhorizflip Mirror image the passed in string. #include \"twr-crt.h\" void twr_strhorizflip(char * buffer, int n); twr_utf8_char_len Returns the number of bytes in a UTF-8 character (passed as a string pointer). UTF-8 characters can be 1 to 4 bytes in length. #include int twr_utf8_char_len(const char *str); twr_utf32_to_code_page Takes a utf32 value (aka unicode code point value), and fills in the passed character array buffer with the character encoding of the utf32 value, using the current locale's LC_CTYPE code page. The buffer is 0 terminated. Also see c32rtomb and c16rtomb . For example: char strbuf[6]; // max size of utf-8 is 4+terminating zero. Max size of ASCII or windows 1252 is 1 + terminating zero setlocale(LC_ALL, \"\"); // set to default locale, which will be UTF-8 encoding with local language/region twr_utf32_to_code_page(strbuf, 0x000020AC); // encode a Euro code point printf(\"%s\", strbuf); assert ( strcmp(strbuf,\"\\xE2\\x82\\xAC\")==0 ); // utf-8 encoding of euro assert ( strcmp(strbuf,\"\u20ac\")==0 ); // clang string literals default to utf-8 encoding include void twr_utf32_to_code_page(char* out, int utf32) twr_vprintf Performs a printf by calling the callback with cbdata for each character. #include \"twr-crt.h\" void twr_vprintf(twr_cbprintf_callback out, void* cbdata, const char *format, va_list* args); floating math helpers int twr_isnan(double v); int twr_isinf(double v); double twr_nanval(); double twr_infval();","title":"C General"},{"location":"api/api-c-general/#general-c-api-for-wasm","text":"","title":"General C API for WASM"},{"location":"api/api-c-general/#overview","text":"This sections describes the \"general\" twr-wasm functions available that don't fit neatly into another category (such as standard C library functions, Draw 2D functions, etc.) These functions often start with \"twr_\" and are generally found in this include file: \\twr-wasm\\include\\twr-crt.h","title":"Overview"},{"location":"api/api-c-general/#bzero","text":"Set a block of memory to zeros. Calls memset(to, 0, count) . #include void bzero (void *to, size_t count);","title":"bzero"},{"location":"api/api-c-general/#getc","text":"This is the standard c library function (see the the standard library docs available on the internet). Of note this function will return extended ASCII (128-255 inclusive). The extend ASCII are always encoded with Windows-1252 encoding. See twr_getc32 for a list of related functions. Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input.","title":"getc"},{"location":"api/api-c-general/#twr_atod","text":"Similar to stdlib atof . #include \"twr-crt.h\" double twr_atod(const char* str);","title":"twr_atod"},{"location":"api/api-c-general/#twr_atou64","text":"Convert a string to a 64 bit unsigned integer, stopping when the first non-valid character is encountered. If len is provided, it will be set to the number of characters read. Radix should be >=2 and <=36 -- for example, 10 is a normal base 10 number and 16 is hexadecimal. #include \"twr-crt.h\" int64_t twr_atou64(const char *str, int* len, int radix);","title":"twr_atou64"},{"location":"api/api-c-general/#twr_dtoa","text":"The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed #include \"twr-crt.h\" void twr_dtoa(char* buffer, int sizeInBytes, double value, int max_precision);","title":"twr_dtoa"},{"location":"api/api-c-general/#twr_cache_mallocfree","text":"These functions keep allocated memory in a cache for much faster re-access than the standard malloc/free. #include \"twr-crt.h\" void *twr_cache_malloc(twr_size_t size); void twr_cache_free(void* mem);","title":"twr_cache_malloc/free"},{"location":"api/api-c-general/#twr_code_page_to_utf32_streamed","text":"Return a unicode code point (aka utf-32 value) when passed a byte stream that represents an encoded character using the current local's LC_CTYPE code page. A zero is returned if the byte stream has not yet completed a decode. For example: int cp setlocale(LC_ALL, \"\"); // set to default locale, which will be UTF-8 encoding with local language/region // turn a UTF-8 Euro into a UTF-32 value cp==twr_code_page_to_utf32_streamed(0xE2); assert (cp==0); cp=twr_code_page_to_utf32_streamed(0x82); assert (cp==0); cp=twr_code_page_to_utf32_streamed(0xAC); assert (cp==0x000020AC); // Euro Code points #include int twr_code_page_to_utf32_streamed(unsigned char byte)","title":"twr_code_page_to_utf32_streamed"},{"location":"api/api-c-general/#twr_conlog","text":"twr_conlog prints debug messages to the browser console from your C code. #include \"twr-crt.h\" void twr_conlog(char* format, ...); Each call to twr_conlog() will generate a single call to console.log() in JavaScript to ensure that you see debug prints. This call is identical to printf, except that it adds a newline. The current implementation does not wait for the debug string to output to the console before returning from twr_conlog, when using twrWasmModuleAsync. In this case, it can take a small bit of time for the string to make its way across the Worker Thread boundary. This is normally not a problem and results in faster performance. But if your code crashes soon after the debug print, the print might not appear. If you think this is an issue, you can call twr_sleep(1) after your twr_conlog call. This will force a blocking wait for the print to print. Prior to 1.0, this function was called twr_dbg_printf , and operated slightly differently.","title":"twr_conlog"},{"location":"api/api-c-general/#twr_epoch_timems","text":"Returns the number of milliseconds since the start of the epoch. #include \"twr-wasm.h\" uint64_t twr_epoch_timems();","title":"twr_epoch_timems"},{"location":"api/api-c-general/#twr_getc32","text":"Gets a 32 bit unicode code point character from stdin . Unlike the standard C library function getchar , twr_getc32 does not buffer a line (that is, twr_getc32 will return a character before the user presses Enter). twr_getc32 is implemented as: int twr_getc32() { return io_getc32(twr_get_stdio_con()); } Note that stdlib getchar and ungetc are not currently implemented. Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input. Also see: io_mbgets - get a multibyte string from a console using the current locale character encoding twr_mbgets - similar to io_mbgets , except always gets a multibyte locale format string from stdin. io_mbgetc - get a multibyte character from an IoConsole (like stdin ) using the current locale character encoding getc (sames as fgetc ) - get a single byte from a FILE * (IoConsole) -- returning ASCII or extended ASCII (window-1252 encoding) io_getc32 - gets a 32 bit unicode code point from an IoConsole (which currently needs to be stdin) #include \"twr-crt.h\" int twr_getc32();","title":"twr_getc32"},{"location":"api/api-c-general/#twr_get_navlang","text":"Returns the BCP 47 language tag as found in javacript navigator.language . If len is not null, it will be filled in with the string length of the language tag. #include \"twr-crt.h\" const char* twr_get_navlang(int *len);","title":"twr_get_navlang"},{"location":"api/api-c-general/#twr_get_current_locale","text":"extern inline locale_t twr_get_current_locale(void); twr_get_current_locale will return the locale that has been set by setlocale . It can be used to pass to a function that takes a locale_t.","title":"twr_get_current_locale"},{"location":"api/api-c-general/#twr_localize_numeric_string","text":"Functions like twr_dtoa do not localize the decimal point. To get a localized decimal point, you can use printf , or alternately twr_localize_numeric_string to post process a string. For example: char b[10]; strcpy(b, \"1.23\"); twr_localize_numeric_string(b, twr_get_current_locale()); // if locale was set to french, then b is now 1,23 #include void twr_localize_numeric_string(char* str, locale_t locale);","title":"twr_localize_numeric_string"},{"location":"api/api-c-general/#twr_mem_debug_stats","text":"Print memory map and malloc stats to stderr or stdout. (note FILE * is the same as struct IoConsole*) #include void twr_mem_debug_stats(struct IoConsole* outcon);","title":"twr_mem_debug_stats"},{"location":"api/api-c-general/#twr_mbgets","text":"Gets a string from stdin . The string will be in the current locale's character encoding -- ASCII for \"C\", and either UTF-8 or windows-1252 for \"\". See localization . #include \"twr-crt.h\" char* twr_mbgets(char* buffer); Internally this function uses the stdio IoConsole -- see the IoConsole section for more advanced input/output. This function will encode characters as specified by the LC_CTYPE category of the current locale. ASCII is used for \"C\", and UTF-8 and Windows-1252 are also supported (see localization ) Note that C character input is blocking and you must use twrWasmModuleAsync -- see stdin for details on how to enable blocking character input.","title":"twr_mbgets"},{"location":"api/api-c-general/#twr_mbslen_l","text":"Returns the number of characters in a string using the character encoding of the passed locale (ASCII for \"C\", UTF-8, or windows-1252 for \"\"). You can use twr_get_current_locale to find the current locale. #include size_t twr_mbslen_l(const char *str, locale_t locale);","title":"twr_mbslen_l"},{"location":"api/api-c-general/#twr_sleep","text":"twr_sleep is a traditional blocking sleep function. This function is blocking, and you must use twrWasmModuleAsync. #include \"twr-wasm.h\" void twr_sleep(int ms);","title":"twr_sleep"},{"location":"api/api-c-general/#twr_tofixed","text":"This function is identical to its JavaScript version. #include \"twr-wasm.h\" void twr_tofixed(char* buffer, int buffer_size, double value, int dec_digits); The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed","title":"twr_tofixed"},{"location":"api/api-c-general/#twr_toexponential","text":"This function is identical to its JavaScript version. #include \"twr-wasm.h\" void twr_toexponential(char* buffer, int buffer_size, double value, int dec_digits); The functions to convert double to text are snprintf , fcvt_s , twr_dtoa , twr_toexponential , and twr_tofixed","title":"twr_toexponential"},{"location":"api/api-c-general/#twr_strhorizflip","text":"Mirror image the passed in string. #include \"twr-crt.h\" void twr_strhorizflip(char * buffer, int n);","title":"twr_strhorizflip"},{"location":"api/api-c-general/#twr_utf8_char_len","text":"Returns the number of bytes in a UTF-8 character (passed as a string pointer). UTF-8 characters can be 1 to 4 bytes in length. #include int twr_utf8_char_len(const char *str);","title":"twr_utf8_char_len"},{"location":"api/api-c-general/#twr_utf32_to_code_page","text":"Takes a utf32 value (aka unicode code point value), and fills in the passed character array buffer with the character encoding of the utf32 value, using the current locale's LC_CTYPE code page. The buffer is 0 terminated. Also see c32rtomb and c16rtomb . For example: char strbuf[6]; // max size of utf-8 is 4+terminating zero. Max size of ASCII or windows 1252 is 1 + terminating zero setlocale(LC_ALL, \"\"); // set to default locale, which will be UTF-8 encoding with local language/region twr_utf32_to_code_page(strbuf, 0x000020AC); // encode a Euro code point printf(\"%s\", strbuf); assert ( strcmp(strbuf,\"\\xE2\\x82\\xAC\")==0 ); // utf-8 encoding of euro assert ( strcmp(strbuf,\"\u20ac\")==0 ); // clang string literals default to utf-8 encoding include void twr_utf32_to_code_page(char* out, int utf32)","title":"twr_utf32_to_code_page"},{"location":"api/api-c-general/#twr_vprintf","text":"Performs a printf by calling the callback with cbdata for each character. #include \"twr-crt.h\" void twr_vprintf(twr_cbprintf_callback out, void* cbdata, const char *format, va_list* args);","title":"twr_vprintf"},{"location":"api/api-c-general/#floating-math-helpers","text":"int twr_isnan(double v); int twr_isinf(double v); double twr_nanval(); double twr_infval();","title":"floating math helpers"},{"location":"api/api-c-stdlib/","text":"Standard C library for Web Assembly This section describes twr-wasm's support for the Standard C Library. twr-wasm includes its own implementation of the standard C library optimized for Web Assembly and wasm running in a web browser. This is a core feature of twr-wasm. For documentation of these functions, see the many standard C library documentation web sites. The following subset of the standard C library is available. Also see twr-wasm/include folder for include files. stdio.h * fprintf will only work with these -- stderr, stdin, stdout */ /* these return 'struct IoConsole *' which is same as 'FILE *' */ #define stderr (FILE *)(twr_get_stderr_con()) #define stdin (FILE *)(twr_get_stdio_con()) #define stdout (FILE *)(twr_get_stdio_con()) int snprintf(char *buffer, size_t bufsz, const char *format, ... ); int sprintf( char *buffer, const char *format, ... ); int vsnprintf(char *buffer, size_t bufsz, const char *format, va_list vlist); int vasprintf(char **strp, const char* format, va_list vlist ); int printf(const char* format, ...); int vprintf(const char* format, va_list vlist ); int puts(const char *str); int putchar(int c); typedef struct IoConsole FILE; int vfprintf(FILE *stream, const char *format, va_list vlist); int fprintf(FILE *stream, const char* format, ...); size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream); int ferror(FILE *stream); int feof(FILE *stream); int fflush(FILE *stream); int is_terminal(FILE *stream); int fputc(int ch, FILE* stream); int putc(int ch, FILE* stream); int fgetc(FILE *stream ); int getc(FILE *stream); stdlib.h void *malloc(size_t size); void free(void *mem); size_t avail(void); void *realloc( void *ptr, size_t new_size ); void* calloc( size_t num, size_t size ); void *aligned_alloc( size_t alignment, size_t size ); int rand(void); void srand(int seed); #define __min(a,b) (((a) < (b)) ? (a) : (b)) #define __max(a,b) (((a) > (b)) ? (a) : (b)) int _fcvt_s( char* buffer, size_t sizeInBytes, double value, int fracpart_numdigits, int *dec, int *sign ); double atof(const char* str); int atoi(const char *str); long atol( const char *str ); long long atoll( const char *str ); long strtol(const char *str, char **str_end, int base); long long strtoll(const char *str, char **str_end, int base); long long strtoll_l(const char *str, char **str_end, int base, locale_t loc); unsigned long long strtoull(const char *str, char **str_end, int base); unsigned long long strtoull_l(const char *str, char **str_end, int base, locale_t loc); unsigned long strtoul(const char *str, char ** str_end, int base); float strtof(const char *str, char ** str_end); float strtof_l(const char *str, char ** str_end, locale_t locale); double strtod(const char *str, char **str_end); double strtod_l(const char *str, char **str_end, locale_t locale); long double strtold(const char *str, char **str_end); long double strtold_l(const char *str, char **str_end, locale_t locale); int _itoa_s(int64_t value, char * buffer, size_t size, int radix); div_t div( int x, int y ); ldiv_t ldiv( long x, long y ); lldiv_t lldiv( long long x, long long y ); _Noreturn void abort(void); int atexit(void (*func)(void)); Note that _fcvt_s as currently enabled has these limitations: - fractional digits <=100 - values must be less than 1e+21 - values negative exponents must be smaller than 1e-99 There is a full featured version of _fcvt_s in the source code, but is not currently enabled, since the version enabled is smaller and works in most use cases. assert.h void assert(int expression); math.h int abs(int n); double acos(double arg); double asin(double arg); double atan(double arg); double ceil(double arg); double cos(double arg); double exp(double arg); double fabs(double arg); double floor(double arg); double fmod(double x, double y); double log(double arg); double pow(double base, double exp); double sin(double arg); double sqrt(double arg); double tan(double arg); double trunc(double arg); stdarg.h #define va_start(v,l) __builtin_va_start(v,l) #define va_end(v) __builtin_va_end(v) #define va_arg(v,l) __builtin_va_arg(v,l) #define va_copy(d,s) __builtin_va_copy(d,s) typedef __builtin_va_list va_list; ctype.h int isascii(int); int toascii(int); int isalnum(int c); int isalpha(int c); int isblank(int); int iscntrl(int); int isdigit(int c); int isgraph(int c); int islower(int); int isprint(int); int ispunct(int); int isspace(int c); int isupper(int); int isxdigit(int); int tolower(int c); int toupper(int c); int isalnum_l(int c, locale_t loc); int isalpha_l(int c, locale_t loc); int isblank_l(int c, locale_t loc); int iscntrl_l(int c, locale_t loc); int isdigit_l(int c, locale_t loc); int isgraph_l(int c, locale_t loc); int islower_l(int c, locale_t loc); int isprint_l(int c, locale_t loc); int ispunct_l(int c, locale_t loc); int isspace_l(int c, locale_t loc); int isupper_l(int c, locale_t loc); int isxdigit_l(int c, locale_t loc); int tolower_l(int c, locale_t loc); int toupper_l(int c, locale_t loc); _stdtypes.h // don't include directly -- included by various .h files typedef unsigned long size_t; #define MAX_SIZE_T 2147483647 #ifdef __cplusplus #define NULL __null #else #define NULL ((void*)0) #endif typedef struct __locale_t_struct * locale_t; stddef.h #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef double max_align_t; string.h size_t strlen(const char * str); char *strdup(const char * source); char *strcpy(char *dest, const char *source); int strcat_s(char *dest, size_t destsz, const char *src); char* strcat(char *dest, const char *src); char *strncpy(char *dest, const char *source, size_t count); int strcmp(const char* string1, const char* string2); int strncmp(const char* lhs, const char* rhs, size_t count); int stricmp(const char* string1, const char* string2); int strnicmp(const char* string1, const char* string2, size_t count); int strcoll(const char* lhs, const char* rhs); int strcoll_l(const char* lhs, const char* rhs, locale_t loc); char *strchr(const char *str, int ch); void *memchr(const void *ptr, int ch, size_t count); char *strstr(const char *haystack, const char *needle); char * strerror(int errnum ); char * _strerror(const char *strErrMsg); void *memmove(void *dest, const void *src, size_t n); int memcmp( const void* lhs, const void* rhs, size_t count ); void bzero (void *to, size_t count); // implemented in memcpy.wat void *memcpy(void *dest, const void * src, size_t n); void *memset(void *mem, int c, size_t n); time.h typedef unsigned long time_t; unsigned long time(unsigned long *time); size_t strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr); size_t strftime_l(char *s, size_t maxsize, const char *format, const struct tm *timeptr, locale_t locale); struct tm *localtime(const time_t *timer); int gettimeofday(struct timeval *tv, void* notused); #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) #define timercmp(tvp,uvp,cmp) \\ ((tvp)->tv_sec cmp (uvp)->tv_sec || \\ ((tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)) #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 locale.h #define LC_GLOBAL_LOCALE twr_get_current_locale() char* setlocale(int category, const char* locale); struct lconv *localeconv(void); locale_t newlocale(int category_mask, const char *locale, locale_t base); locale_t uselocale(locale_t); void freelocale(locale_t); locale_t duplocale(locale_t); extern inline locale_t twr_get_current_locale(void); errno.h typedef int errno_t; extern int * _errno(void); #define errno (*_errno()) errno_t _set_errno(int _Value); errno_t _get_errno(int *_Value); Other include files available float.h limits.h stdbool.h stdint.h","title":"C Standard C Library"},{"location":"api/api-c-stdlib/#standard-c-library-for-web-assembly","text":"This section describes twr-wasm's support for the Standard C Library. twr-wasm includes its own implementation of the standard C library optimized for Web Assembly and wasm running in a web browser. This is a core feature of twr-wasm. For documentation of these functions, see the many standard C library documentation web sites. The following subset of the standard C library is available. Also see twr-wasm/include folder for include files.","title":"Standard C library for Web Assembly"},{"location":"api/api-c-stdlib/#stdioh","text":"* fprintf will only work with these -- stderr, stdin, stdout */ /* these return 'struct IoConsole *' which is same as 'FILE *' */ #define stderr (FILE *)(twr_get_stderr_con()) #define stdin (FILE *)(twr_get_stdio_con()) #define stdout (FILE *)(twr_get_stdio_con()) int snprintf(char *buffer, size_t bufsz, const char *format, ... ); int sprintf( char *buffer, const char *format, ... ); int vsnprintf(char *buffer, size_t bufsz, const char *format, va_list vlist); int vasprintf(char **strp, const char* format, va_list vlist ); int printf(const char* format, ...); int vprintf(const char* format, va_list vlist ); int puts(const char *str); int putchar(int c); typedef struct IoConsole FILE; int vfprintf(FILE *stream, const char *format, va_list vlist); int fprintf(FILE *stream, const char* format, ...); size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream); int ferror(FILE *stream); int feof(FILE *stream); int fflush(FILE *stream); int is_terminal(FILE *stream); int fputc(int ch, FILE* stream); int putc(int ch, FILE* stream); int fgetc(FILE *stream ); int getc(FILE *stream);","title":"stdio.h"},{"location":"api/api-c-stdlib/#stdlibh","text":"void *malloc(size_t size); void free(void *mem); size_t avail(void); void *realloc( void *ptr, size_t new_size ); void* calloc( size_t num, size_t size ); void *aligned_alloc( size_t alignment, size_t size ); int rand(void); void srand(int seed); #define __min(a,b) (((a) < (b)) ? (a) : (b)) #define __max(a,b) (((a) > (b)) ? (a) : (b)) int _fcvt_s( char* buffer, size_t sizeInBytes, double value, int fracpart_numdigits, int *dec, int *sign ); double atof(const char* str); int atoi(const char *str); long atol( const char *str ); long long atoll( const char *str ); long strtol(const char *str, char **str_end, int base); long long strtoll(const char *str, char **str_end, int base); long long strtoll_l(const char *str, char **str_end, int base, locale_t loc); unsigned long long strtoull(const char *str, char **str_end, int base); unsigned long long strtoull_l(const char *str, char **str_end, int base, locale_t loc); unsigned long strtoul(const char *str, char ** str_end, int base); float strtof(const char *str, char ** str_end); float strtof_l(const char *str, char ** str_end, locale_t locale); double strtod(const char *str, char **str_end); double strtod_l(const char *str, char **str_end, locale_t locale); long double strtold(const char *str, char **str_end); long double strtold_l(const char *str, char **str_end, locale_t locale); int _itoa_s(int64_t value, char * buffer, size_t size, int radix); div_t div( int x, int y ); ldiv_t ldiv( long x, long y ); lldiv_t lldiv( long long x, long long y ); _Noreturn void abort(void); int atexit(void (*func)(void)); Note that _fcvt_s as currently enabled has these limitations: - fractional digits <=100 - values must be less than 1e+21 - values negative exponents must be smaller than 1e-99 There is a full featured version of _fcvt_s in the source code, but is not currently enabled, since the version enabled is smaller and works in most use cases.","title":"stdlib.h"},{"location":"api/api-c-stdlib/#asserth","text":"void assert(int expression);","title":"assert.h"},{"location":"api/api-c-stdlib/#mathh","text":"int abs(int n); double acos(double arg); double asin(double arg); double atan(double arg); double ceil(double arg); double cos(double arg); double exp(double arg); double fabs(double arg); double floor(double arg); double fmod(double x, double y); double log(double arg); double pow(double base, double exp); double sin(double arg); double sqrt(double arg); double tan(double arg); double trunc(double arg);","title":"math.h"},{"location":"api/api-c-stdlib/#stdargh","text":"#define va_start(v,l) __builtin_va_start(v,l) #define va_end(v) __builtin_va_end(v) #define va_arg(v,l) __builtin_va_arg(v,l) #define va_copy(d,s) __builtin_va_copy(d,s) typedef __builtin_va_list va_list;","title":"stdarg.h"},{"location":"api/api-c-stdlib/#ctypeh","text":"int isascii(int); int toascii(int); int isalnum(int c); int isalpha(int c); int isblank(int); int iscntrl(int); int isdigit(int c); int isgraph(int c); int islower(int); int isprint(int); int ispunct(int); int isspace(int c); int isupper(int); int isxdigit(int); int tolower(int c); int toupper(int c); int isalnum_l(int c, locale_t loc); int isalpha_l(int c, locale_t loc); int isblank_l(int c, locale_t loc); int iscntrl_l(int c, locale_t loc); int isdigit_l(int c, locale_t loc); int isgraph_l(int c, locale_t loc); int islower_l(int c, locale_t loc); int isprint_l(int c, locale_t loc); int ispunct_l(int c, locale_t loc); int isspace_l(int c, locale_t loc); int isupper_l(int c, locale_t loc); int isxdigit_l(int c, locale_t loc); int tolower_l(int c, locale_t loc); int toupper_l(int c, locale_t loc);","title":"ctype.h"},{"location":"api/api-c-stdlib/#_stdtypesh","text":"// don't include directly -- included by various .h files typedef unsigned long size_t; #define MAX_SIZE_T 2147483647 #ifdef __cplusplus #define NULL __null #else #define NULL ((void*)0) #endif typedef struct __locale_t_struct * locale_t;","title":"_stdtypes.h"},{"location":"api/api-c-stdlib/#stddefh","text":"#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef double max_align_t;","title":"stddef.h"},{"location":"api/api-c-stdlib/#stringh","text":"size_t strlen(const char * str); char *strdup(const char * source); char *strcpy(char *dest, const char *source); int strcat_s(char *dest, size_t destsz, const char *src); char* strcat(char *dest, const char *src); char *strncpy(char *dest, const char *source, size_t count); int strcmp(const char* string1, const char* string2); int strncmp(const char* lhs, const char* rhs, size_t count); int stricmp(const char* string1, const char* string2); int strnicmp(const char* string1, const char* string2, size_t count); int strcoll(const char* lhs, const char* rhs); int strcoll_l(const char* lhs, const char* rhs, locale_t loc); char *strchr(const char *str, int ch); void *memchr(const void *ptr, int ch, size_t count); char *strstr(const char *haystack, const char *needle); char * strerror(int errnum ); char * _strerror(const char *strErrMsg); void *memmove(void *dest, const void *src, size_t n); int memcmp( const void* lhs, const void* rhs, size_t count ); void bzero (void *to, size_t count); // implemented in memcpy.wat void *memcpy(void *dest, const void * src, size_t n); void *memset(void *mem, int c, size_t n);","title":"string.h"},{"location":"api/api-c-stdlib/#timeh","text":"typedef unsigned long time_t; unsigned long time(unsigned long *time); size_t strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr); size_t strftime_l(char *s, size_t maxsize, const char *format, const struct tm *timeptr, locale_t locale); struct tm *localtime(const time_t *timer); int gettimeofday(struct timeval *tv, void* notused); #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) #define timercmp(tvp,uvp,cmp) \\ ((tvp)->tv_sec cmp (uvp)->tv_sec || \\ ((tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)) #define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0","title":"time.h"},{"location":"api/api-c-stdlib/#localeh","text":"#define LC_GLOBAL_LOCALE twr_get_current_locale() char* setlocale(int category, const char* locale); struct lconv *localeconv(void); locale_t newlocale(int category_mask, const char *locale, locale_t base); locale_t uselocale(locale_t); void freelocale(locale_t); locale_t duplocale(locale_t); extern inline locale_t twr_get_current_locale(void);","title":"locale.h"},{"location":"api/api-c-stdlib/#errnoh","text":"typedef int errno_t; extern int * _errno(void); #define errno (*_errno()) errno_t _set_errno(int _Value); errno_t _get_errno(int *_Value);","title":"errno.h"},{"location":"api/api-c-stdlib/#other-include-files-available","text":"float.h limits.h stdbool.h stdint.h","title":"Other include files available"},{"location":"api/api-libc%2B%2B/","text":"libc++ for Web Assembly This section describes twr-wasm's support for using the standard c++ library libc++ with Web Assembly. twr-wasm includes libc++ built for Web Assembly and included in the twr-wasm/lib-c folder. For C++ the use of libc++ is optional. That is you can build twr-wasm projects in C++ with or without libc++. See the examples tests-libcxx and tests-user for examples of using libc++. See the balls example for how to create a C++ Web Assembly program without the standard C++ library. The primary advantage to this approach is a bit smaller code size. You don't need to staticly link libc++. Some of the key options twr-wasm's libc++ for Web Assembly was built with are these: DLIBCXX_ENABLE_LOCALIZATION=ON DLIBCXX_ENABLE_UNICODE=ON DLIBCXX_ENABLE_RTTI=ON DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON DCMAKE_BUILD_TYPE=Release DCMAKE_CXX_STANDARD=20 DLIBCXX_ENABLE_EXCEPTIONS=OFF DLIBCXX_ENABLE_THREADS=OFF DLIBCXX_ENABLE_SHARED=OFF DLIBCXX_ENABLE_WIDE_CHARACTERS=OFF DLIBCXX_ENABLE_FILESYSTEM=OFF DLIBCXX_ENABLE_TIME_ZONE_DATABASE=OFF DLIBCXX_ENABLE_MONOTONIC_CLOCK=OFF DLIBCXX_ENABLE_RANDOM_DEVICE=OFF","title":"C++ with libc++"},{"location":"api/api-libc%2B%2B/#libc-for-web-assembly","text":"This section describes twr-wasm's support for using the standard c++ library libc++ with Web Assembly. twr-wasm includes libc++ built for Web Assembly and included in the twr-wasm/lib-c folder. For C++ the use of libc++ is optional. That is you can build twr-wasm projects in C++ with or without libc++. See the examples tests-libcxx and tests-user for examples of using libc++. See the balls example for how to create a C++ Web Assembly program without the standard C++ library. The primary advantage to this approach is a bit smaller code size. You don't need to staticly link libc++. Some of the key options twr-wasm's libc++ for Web Assembly was built with are these: DLIBCXX_ENABLE_LOCALIZATION=ON DLIBCXX_ENABLE_UNICODE=ON DLIBCXX_ENABLE_RTTI=ON DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON DCMAKE_BUILD_TYPE=Release DCMAKE_CXX_STANDARD=20 DLIBCXX_ENABLE_EXCEPTIONS=OFF DLIBCXX_ENABLE_THREADS=OFF DLIBCXX_ENABLE_SHARED=OFF DLIBCXX_ENABLE_WIDE_CHARACTERS=OFF DLIBCXX_ENABLE_FILESYSTEM=OFF DLIBCXX_ENABLE_TIME_ZONE_DATABASE=OFF DLIBCXX_ENABLE_MONOTONIC_CLOCK=OFF DLIBCXX_ENABLE_RANDOM_DEVICE=OFF","title":"libc++ for Web Assembly"},{"location":"api/api-localization/","text":"Locale Support for Web Assembly This section explains twr-wasm's Web Assembly localization support. Character encodings twr-wasm locales supports ASCII, UTF-8 or windows-1252 encoding. UTF-16/32 are not supported as a locale setting, but functions are provided to convert utf-32 (unicode code points) to and from ASCII, UTF-8, and windows-1252 \"code pages\" (there are other miscellaneous utf-32 based functions as well.) UTF-8 uses between one to four bytes to represent any unicode character, with ASCII compatibility in the first 128 bytes. It is also the standard for the web, and the default for clang. But because it uses a variable number of bytes per character it can make string manipulation in C a bit harder than ASCII. Windows-1252 is the default on most Windows computers in many countries - particularly the Americas and western Europe. It is an extension of ASCII that uses a single byte per character. This makes it easier than UTF-8 from a programmers perspective, but it doesn't represent as many characters. It is provided to make it easier to port legacy C code, windows code, as well as a simpler alternative to UTF-8. Although the locale settings don't support utf-32 directly, you can use int arrays (instead of byte arrays) to hold utf-32 strings, and then convert them to/from utf-8 with the help of the provided two functions for this purpose. Locales \"C\" \"C\" is the default locale, as usual. When \"C\" is selected, the functions operate as usual. One subtly is that console i/o functions (such as printf ) will generally function as expected with UTF-8, since the div and window consoles correctly handle UTF-8 character encoding. This is normal on some OSs, such as linux, but not the default on Windows (which often defaults to windows-1252 for backward compatibility). isgraph style functions will only recognize ASCII characters, as is normal. Functions such as strcmp operate on the byte sequence, which will typically results in UTF-8 codes being compared lexically. strcoll will use lexical ordering. \"POSIX\" \"POSIX\" is the same as \"C\" \"\" \"\" is the locale to specify the users default setting (this selects the setting used by the browser). This will also enable UTF-8 in functions such as strcoll . For example, if your browser is set to \"en-US\" as its default locale, setlocale(LC_ALL, \"\") will return en-US.UTF-8 . isgraph style functions will still only recognize ASCII characters (since UTF-8 doesn't encode any single bytes greater than 127). strcoll uses locale specific ordering, and printf will use locale specific decimal points. strcmp still compares two strings lexicographically (byte-by-byte) without considering locale-specific rules, per the spec. \".UTF-8\" \".UTF-8\" is the same as \"\" with twr-wasm. \".1252\" \".1252\" will select the current default locale, but use windows-1252 character encoding (instead of UTF-8). Windows-1252 is a super set of ISO-8859-1 and is the most commonly used encoding for many european languages when unicode is not used. This mode is primarily for legacy software, backwards compatibly, and windows compatibility. 1252 String Literals These days text editors generally default to UTF-8. In order to use windows-1252 source code and/or string literals, such as const char * str=\"\u20ac100\" you may need to: Configure your text editor to save in Windows-1252/ISO-8859-1 format (instead of UTF-8) use compiler flags like --finput-charset and -fexec-charset By default, the Microsoft Visual Studio C compiler (MSVC) does not treat string literals as UTF-8. Instead, it treats them as being encoded in the current code page of the system, which is typically Windows-1252 on western european language Windows systems. twr-wasm is designed to work with clang, which does default to utf-8, so if you are compiling code written for MSVC, and you use extend character sets (non ASCII), you may need to adjust your compiler settings with the flags mentioned above. Others Setting arbitrary locales, such as \"fr-FR\" when the browser is defaulted to another locale, is not supported. Select the default locale To select the user's browser's default locale using the C language, and enable consistent utf-8 support, use a call like this: setlocale(LC_ALL, \"\") libc++ If you are using C++, libc++ locale functions work as expected. C functions The normal standard C library locale support is available, along with some POSIX extensions. In addition, some locale useful twr-wasm specific functions are documented in C API , such as twr_get_current_locale , twr_mbgets , twr_getc32 , twr_utf8_char_len , twr_mbslen_l , twr_utf32_to_code_page , twr_code_page_to_utf32_streamed , twr_get_navlang , twr_localize_numeric_string . Note that io_getc32() , getc(stdin) , fgetc(stdin) do not look at the current locale. iogetc32 returns a 32 bit unicode code point, and getc / fgetc return extended ASCII. For a locale aware character input, use io_mbgetc() or twr_mbgets() . Both use the locale category LC_CTYPE. See C API . Note that when the locale is not set (or whenever the \"C\" locale is set) functions that get character(s) from stdin that are locale aware, like twr_mbgets() , behave different than functions that output characters to stdout (like puts , io_putstr , io_putc , putchar ). Characters to stdout in \"C\" locale will handle UTF-8 characters. For stdin, \"C\" locale uses ASCII. For consistent UTF-8 (or windows-1252) behavior, set the locale as discussed above ( use setlocale ) The primary standard C library locale functions are: char* setlocale(int category, const char* locale); struct lconv *localeconv(void); As well as the standard library functions above, appropriate functions take into account the current locale (printf, strcoll, etc). Note that setlocale returns a string using BCP 47 format (similar to a web browser). Locale strings look like \"en-US.UTF-8\", instead of \"en_US.UTF-8\". A dash, not an underscore, is used as a separator. POSIX functions These are the extended POSIX style functions provided that are related to locale: locale_t newlocale(int category_mask, const char *locale, locale_t base); locale_t uselocale(locale_t); void freelocale(locale_t); locale_t duplocale(locale_t); int isalnum_l(int c, locale_t loc); int isalpha_l(int c, locale_t loc); int isblank_l(int c, locale_t loc); int iscntrl_l(int c, locale_t loc); int isdigit_l(int c, locale_t loc); int isgraph_l(int c, locale_t loc); int islower_l(int c, locale_t loc); int isprint_l(int c, locale_t loc); int ispunct_l(int c, locale_t loc); int isspace_l(int c, locale_t loc); int isupper_l(int c, locale_t loc); int isxdigit_l(int c, locale_t loc); int tolower_l(int c, locale_t loc); int toupper_l(int c, locale_t loc); long long strtoll_l(const char *str, char **str_end, int base, locale_t loc); unsigned long long strtoull_l(const char *str, char **str_end, int base, locale_t loc); float strtof_l(const char *str, char ** str_end, locale_t locale); double strtod_l(const char *str, char **str_end, locale_t locale); long double strtold_l(const char *str, char **str_end, locale_t locale); int strcoll_l(const char* lhs, const char* rhs, locale_t loc); size_t strftime_l(char *s, size_t maxsize, const char *format, const struct tm *timeptr, locale_t locale);","title":"C Localization"},{"location":"api/api-localization/#locale-support-for-web-assembly","text":"This section explains twr-wasm's Web Assembly localization support.","title":"Locale Support for Web Assembly"},{"location":"api/api-localization/#character-encodings","text":"twr-wasm locales supports ASCII, UTF-8 or windows-1252 encoding. UTF-16/32 are not supported as a locale setting, but functions are provided to convert utf-32 (unicode code points) to and from ASCII, UTF-8, and windows-1252 \"code pages\" (there are other miscellaneous utf-32 based functions as well.) UTF-8 uses between one to four bytes to represent any unicode character, with ASCII compatibility in the first 128 bytes. It is also the standard for the web, and the default for clang. But because it uses a variable number of bytes per character it can make string manipulation in C a bit harder than ASCII. Windows-1252 is the default on most Windows computers in many countries - particularly the Americas and western Europe. It is an extension of ASCII that uses a single byte per character. This makes it easier than UTF-8 from a programmers perspective, but it doesn't represent as many characters. It is provided to make it easier to port legacy C code, windows code, as well as a simpler alternative to UTF-8. Although the locale settings don't support utf-32 directly, you can use int arrays (instead of byte arrays) to hold utf-32 strings, and then convert them to/from utf-8 with the help of the provided two functions for this purpose.","title":"Character encodings"},{"location":"api/api-localization/#locales","text":"","title":"Locales"},{"location":"api/api-localization/#c","text":"\"C\" is the default locale, as usual. When \"C\" is selected, the functions operate as usual. One subtly is that console i/o functions (such as printf ) will generally function as expected with UTF-8, since the div and window consoles correctly handle UTF-8 character encoding. This is normal on some OSs, such as linux, but not the default on Windows (which often defaults to windows-1252 for backward compatibility). isgraph style functions will only recognize ASCII characters, as is normal. Functions such as strcmp operate on the byte sequence, which will typically results in UTF-8 codes being compared lexically. strcoll will use lexical ordering.","title":"\"C\""},{"location":"api/api-localization/#posix","text":"\"POSIX\" is the same as \"C\"","title":"\"POSIX\""},{"location":"api/api-localization/#_1","text":"\"\" is the locale to specify the users default setting (this selects the setting used by the browser). This will also enable UTF-8 in functions such as strcoll . For example, if your browser is set to \"en-US\" as its default locale, setlocale(LC_ALL, \"\") will return en-US.UTF-8 . isgraph style functions will still only recognize ASCII characters (since UTF-8 doesn't encode any single bytes greater than 127). strcoll uses locale specific ordering, and printf will use locale specific decimal points. strcmp still compares two strings lexicographically (byte-by-byte) without considering locale-specific rules, per the spec.","title":"\"\""},{"location":"api/api-localization/#utf-8","text":"\".UTF-8\" is the same as \"\" with twr-wasm.","title":"\".UTF-8\""},{"location":"api/api-localization/#1252","text":"\".1252\" will select the current default locale, but use windows-1252 character encoding (instead of UTF-8). Windows-1252 is a super set of ISO-8859-1 and is the most commonly used encoding for many european languages when unicode is not used. This mode is primarily for legacy software, backwards compatibly, and windows compatibility. 1252 String Literals These days text editors generally default to UTF-8. In order to use windows-1252 source code and/or string literals, such as const char * str=\"\u20ac100\" you may need to: Configure your text editor to save in Windows-1252/ISO-8859-1 format (instead of UTF-8) use compiler flags like --finput-charset and -fexec-charset By default, the Microsoft Visual Studio C compiler (MSVC) does not treat string literals as UTF-8. Instead, it treats them as being encoded in the current code page of the system, which is typically Windows-1252 on western european language Windows systems. twr-wasm is designed to work with clang, which does default to utf-8, so if you are compiling code written for MSVC, and you use extend character sets (non ASCII), you may need to adjust your compiler settings with the flags mentioned above.","title":"\".1252\""},{"location":"api/api-localization/#others","text":"Setting arbitrary locales, such as \"fr-FR\" when the browser is defaulted to another locale, is not supported.","title":"Others"},{"location":"api/api-localization/#select-the-default-locale","text":"To select the user's browser's default locale using the C language, and enable consistent utf-8 support, use a call like this: setlocale(LC_ALL, \"\")","title":"Select the default locale"},{"location":"api/api-localization/#libc","text":"If you are using C++, libc++ locale functions work as expected.","title":"libc++"},{"location":"api/api-localization/#c-functions","text":"The normal standard C library locale support is available, along with some POSIX extensions. In addition, some locale useful twr-wasm specific functions are documented in C API , such as twr_get_current_locale , twr_mbgets , twr_getc32 , twr_utf8_char_len , twr_mbslen_l , twr_utf32_to_code_page , twr_code_page_to_utf32_streamed , twr_get_navlang , twr_localize_numeric_string . Note that io_getc32() , getc(stdin) , fgetc(stdin) do not look at the current locale. iogetc32 returns a 32 bit unicode code point, and getc / fgetc return extended ASCII. For a locale aware character input, use io_mbgetc() or twr_mbgets() . Both use the locale category LC_CTYPE. See C API . Note that when the locale is not set (or whenever the \"C\" locale is set) functions that get character(s) from stdin that are locale aware, like twr_mbgets() , behave different than functions that output characters to stdout (like puts , io_putstr , io_putc , putchar ). Characters to stdout in \"C\" locale will handle UTF-8 characters. For stdin, \"C\" locale uses ASCII. For consistent UTF-8 (or windows-1252) behavior, set the locale as discussed above ( use setlocale ) The primary standard C library locale functions are: char* setlocale(int category, const char* locale); struct lconv *localeconv(void); As well as the standard library functions above, appropriate functions take into account the current locale (printf, strcoll, etc). Note that setlocale returns a string using BCP 47 format (similar to a web browser). Locale strings look like \"en-US.UTF-8\", instead of \"en_US.UTF-8\". A dash, not an underscore, is used as a separator.","title":"C functions"},{"location":"api/api-localization/#posix-functions","text":"These are the extended POSIX style functions provided that are related to locale: locale_t newlocale(int category_mask, const char *locale, locale_t base); locale_t uselocale(locale_t); void freelocale(locale_t); locale_t duplocale(locale_t); int isalnum_l(int c, locale_t loc); int isalpha_l(int c, locale_t loc); int isblank_l(int c, locale_t loc); int iscntrl_l(int c, locale_t loc); int isdigit_l(int c, locale_t loc); int isgraph_l(int c, locale_t loc); int islower_l(int c, locale_t loc); int isprint_l(int c, locale_t loc); int ispunct_l(int c, locale_t loc); int isspace_l(int c, locale_t loc); int isupper_l(int c, locale_t loc); int isxdigit_l(int c, locale_t loc); int tolower_l(int c, locale_t loc); int toupper_l(int c, locale_t loc); long long strtoll_l(const char *str, char **str_end, int base, locale_t loc); unsigned long long strtoull_l(const char *str, char **str_end, int base, locale_t loc); float strtof_l(const char *str, char ** str_end, locale_t locale); double strtod_l(const char *str, char **str_end, locale_t locale); long double strtold_l(const char *str, char **str_end, locale_t locale); int strcoll_l(const char* lhs, const char* rhs, locale_t loc); size_t strftime_l(char *s, size_t maxsize, const char *format, const struct tm *timeptr, locale_t locale);","title":"POSIX functions"},{"location":"api/api-typescript/","text":"TypeScript-JavaScript API for WASM This section describes the twr-wasm TypeScript/JavaScript classes that you use to load your wasm modules, and to call C functions in your wasm modules. class twrWasmModule and class twrWasmModuleAsync have similar APIs. The primary difference is that class twrWasmModuleAsync proxies functionality through a Web Worker thread, which allows blocking C functions to be called in your Web Assembly Module. class twrWasmModule import {twrWasmModule} from \"twr-wasm\"; const mod = new twrWasmModule(); twrWasmModule provides the two core JavaScript APIs for access to a Web Assembly Module: loadWasm to load your .wasm module (your compiled C code). callC to call a C function These functions are documented further down in this section. class twrWasmModuleAsync import {twrWasmModuleAsync} from \"twr-wasm\"; const amod = new twrWasmModuleAsync(); twrWasmModuleAsync implements all of the same functions as twrWasmModule , plus allows blocking inputs, and blocking code generally. This is achieved by proxying all the calls through a Web Worker thread. Use twrWasmModuleAsync if your C code blocks, or if you are unsure. If you want better performance and don't need the capabilities of twrWasmModuleAsync , use twrWasmModule . You must use twrWasmModuleAsync in order to: call any blocking C function (meaning it takes \"a long time\") to return use blocking input from a div or canvas ( eg. twr_mbgets ) use twr_sleep See stdio section for information on enabling blocking character input, as well as this Example . When comping/linking your C/C++ code, twrWasmModule and twrWasmModuleAsync use slightly different wasm-ld options since twrWasmModuleAsync uses shared memory. wrWasmModule will operate with shared memory, so technically you could just use the same share memory options with either module, but you don't need the overhead of shared memory when using twrWasmModule, and so better to not enable it. See Compiler Options . twrWasmModuleAsync uses SharedArrayBuffers which require certain HTTP headers to be set. Note that twrWasmModule has an advantage in that it does not use SharedArrayBuffers. Github pages doesn't support the needed CORS headers for SharedArrayBuffers. But other web serving sites do have options to enable the needed CORS headers. For example, the azure static web site config file staticwebapp.config.json looks like this: { \"globalHeaders\": { \"Access-Control-Allow-Origin\": \"*\", \"Cross-Origin-Embedder-Policy\": \"require-corp\", \"Cross-Origin-Opener-Policy\": \"same-origin\" } } server.py in the examples folder will launch a local server with the correct headers. To use Chrome without a web server, see the debugging section . Class Options The twrWasmModule and twrWasmModuleAsync constructor both take optional options. For example: let amod=new twrWasmModuleAsync(); let amod=new twrWasmModuleAsync({ windim:[50,20], forecolor:\"beige\", backcolor:\"DarkOliveGreen\", fontsize:18 }); For a
      it is simpler to set the color and font in the div tag per the normal HTML method. But for
      , that method won't work and you need to use the constructor options for color and fontsize. These are the options: export type TStdioVals=\"div\"|\"canvas\"|\"null\"|\"debug\"; export interface IModOpts { stdio?:TStdioVals, windim?:[number, number], forecolor?:string, backcolor?:string, fontsize?:number, imports?:{}, } stdio You can explicitly set your stdio source (for C/C++ printf, etc) with the stdio option, but typically you don't set it. Instead, it will auto set as described here windim This options is used with a terminal console ( ) to set the width and height, in characters. The canvas width and height, in pixels, will be set based on your fontsize and the width and height (in characters) of the terminal. forecolor and backcolor These can be set to a CSS color (like '#FFFFFF' or 'white') to change the default background and foreground colors. fonsize Changes the default fontsize for div or canvas based I/O. The size is in pixels. loadWasm Use loadWasm to load your compiled C/C++ code (the .wasm file). await mod.loadWasm(\"./mycode.wasm\") callC After your . wasm module is loaded with loadWasm , you call functions in your C/C++ from TypeScript/JavaScript like this: let result=await amod.callC([\"bounce_balls_move\", param1]) If you are calling into C++, you need to use extern \"C\" like this in your C++ code: extern \"C\" int bounce_balls_move() {} Each C/C++ function that you wish to call from TypeScript/JavaScript needs to be exported in your wasm-ld settings like this: --export=bounce_balls_move Or like this in your source file: __attribute__((export_name(\"bounce_balls_move\"))) void bounce_balls_move() { ... See the Compiler Options . callC takes an array where: the first entry is the name of the C function in the wasm module to call and the next entries are a variable number of parameters to pass to the C function, of type: number - will be converted to int32 or float64 as appropriate string - converted to a pointer to module Memory where string is copied into ArrayBuffer - the array is loaded into module memory. If you need to pass the length, pass it as a separate parameter. Any modifications to the memory made by your C code will be reflected back into the JavaScript ArrayBuffer. URL - the url contents are loaded into module Memory, and two C parameters are generated - index (pointer) to the memory, and length callC returns the value returned by the C function that was called. As well int and float , string and structs (or blocks of memory) can be returned. More details can be found in examples/function-calls . The FFT example demonstrates passing a Float32Array view of an ArrayBuffer. Also see Key Concepts . divLog If stdio is set to twr_iodiv , you can use the divLog twrWasmModule/Async function like this: import {twrWasmModule} from \"twr-wasm\"; const mod = new twrWasmModule(); await mod.loadWasm(\"./tests.wasm\"); await mod.callC([\"tests\"]); mod.divLog(\"\\nsin() speed test\"); let sumA=0; const start=Date.now(); for (let i=0; i<2000000;i++) sumA=sumA+Math.sin(i); const endA=Date.now(); let sumB=await mod.callC([\"sin_test\"]); const endB=Date.now(); mod.divLog(\"sum A: \", sumA, \" in ms: \", endA-start); mod.divLog(\"sum B: \", sumB, \" in ms: \", endB-endA); Accessing Data in the Web Assembly Memory You probably will not need to use the twrWasmModule/Async functions in this section, as callC() will convert your parameters for you. But if you return or want to pass in more complicated structs, you might need to. The source in source/twr-wasm-ts/canvas.ts is an example of how these are used. async putString(sin:string, codePage=codePageUTF8) // returns index into WebAssembly.Memory async putU8(u8a:Uint8Array) // returns index into WebAssembly.Memory async putArrayBuffer(ab:ArrayBuffer) // returns index into WebAssembly.Memory async fetchAndPutURL(fnin:URL) // returns index into WebAssembly.Memory async malloc(size:number) // returns index in WebAssembly.Memory. stringToU8(sin:string, codePage=codePageUTF8) copyString(buffer:number, buffer_size:number, sin:string, codePage=codePageUTF8):void getLong(idx:number): number setLong(idx:number, value:number) getDouble(idx:number): number setDouble(idx:number, value:number) getShort(idx:number): number getString(strIndex:number, len?:number, codePage=codePageUTF8): string getU8Arr(idx:number): Uint8Array getU32Arr(idx:number): Uint32Array memory?:WebAssembly.Memory; mem8:Uint8Array; mem32:Uint32Array; memD:Float64Array;","title":"TypeScript/JavaScript"},{"location":"api/api-typescript/#typescript-javascript-api-for-wasm","text":"This section describes the twr-wasm TypeScript/JavaScript classes that you use to load your wasm modules, and to call C functions in your wasm modules. class twrWasmModule and class twrWasmModuleAsync have similar APIs. The primary difference is that class twrWasmModuleAsync proxies functionality through a Web Worker thread, which allows blocking C functions to be called in your Web Assembly Module.","title":"TypeScript-JavaScript API for WASM"},{"location":"api/api-typescript/#class-twrwasmmodule","text":"import {twrWasmModule} from \"twr-wasm\"; const mod = new twrWasmModule(); twrWasmModule provides the two core JavaScript APIs for access to a Web Assembly Module: loadWasm to load your .wasm module (your compiled C code). callC to call a C function These functions are documented further down in this section.","title":"class twrWasmModule"},{"location":"api/api-typescript/#class-twrwasmmoduleasync","text":"import {twrWasmModuleAsync} from \"twr-wasm\"; const amod = new twrWasmModuleAsync(); twrWasmModuleAsync implements all of the same functions as twrWasmModule , plus allows blocking inputs, and blocking code generally. This is achieved by proxying all the calls through a Web Worker thread. Use twrWasmModuleAsync if your C code blocks, or if you are unsure. If you want better performance and don't need the capabilities of twrWasmModuleAsync , use twrWasmModule . You must use twrWasmModuleAsync in order to: call any blocking C function (meaning it takes \"a long time\") to return use blocking input from a div or canvas ( eg. twr_mbgets ) use twr_sleep See stdio section for information on enabling blocking character input, as well as this Example . When comping/linking your C/C++ code, twrWasmModule and twrWasmModuleAsync use slightly different wasm-ld options since twrWasmModuleAsync uses shared memory. wrWasmModule will operate with shared memory, so technically you could just use the same share memory options with either module, but you don't need the overhead of shared memory when using twrWasmModule, and so better to not enable it. See Compiler Options . twrWasmModuleAsync uses SharedArrayBuffers which require certain HTTP headers to be set. Note that twrWasmModule has an advantage in that it does not use SharedArrayBuffers. Github pages doesn't support the needed CORS headers for SharedArrayBuffers. But other web serving sites do have options to enable the needed CORS headers. For example, the azure static web site config file staticwebapp.config.json looks like this: { \"globalHeaders\": { \"Access-Control-Allow-Origin\": \"*\", \"Cross-Origin-Embedder-Policy\": \"require-corp\", \"Cross-Origin-Opener-Policy\": \"same-origin\" } } server.py in the examples folder will launch a local server with the correct headers. To use Chrome without a web server, see the debugging section .","title":"class twrWasmModuleAsync"},{"location":"api/api-typescript/#class-options","text":"The twrWasmModule and twrWasmModuleAsync constructor both take optional options. For example: let amod=new twrWasmModuleAsync(); let amod=new twrWasmModuleAsync({ windim:[50,20], forecolor:\"beige\", backcolor:\"DarkOliveGreen\", fontsize:18 }); For a
      it is simpler to set the color and font in the div tag per the normal HTML method. But for
      , that method won't work and you need to use the constructor options for color and fontsize. These are the options: export type TStdioVals=\"div\"|\"canvas\"|\"null\"|\"debug\"; export interface IModOpts { stdio?:TStdioVals, windim?:[number, number], forecolor?:string, backcolor?:string, fontsize?:number, imports?:{}, }","title":"Class Options"},{"location":"api/api-typescript/#stdio","text":"You can explicitly set your stdio source (for C/C++ printf, etc) with the stdio option, but typically you don't set it. Instead, it will auto set as described here","title":"stdio"},{"location":"api/api-typescript/#windim","text":"This options is used with a terminal console ( ) to set the width and height, in characters. The canvas width and height, in pixels, will be set based on your fontsize and the width and height (in characters) of the terminal.","title":"windim"},{"location":"api/api-typescript/#forecolor-and-backcolor","text":"These can be set to a CSS color (like '#FFFFFF' or 'white') to change the default background and foreground colors.","title":"forecolor and backcolor"},{"location":"api/api-typescript/#fonsize","text":"Changes the default fontsize for div or canvas based I/O. The size is in pixels.","title":"fonsize"},{"location":"api/api-typescript/#loadwasm","text":"Use loadWasm to load your compiled C/C++ code (the .wasm file). await mod.loadWasm(\"./mycode.wasm\")","title":"loadWasm"},{"location":"api/api-typescript/#callc","text":"After your . wasm module is loaded with loadWasm , you call functions in your C/C++ from TypeScript/JavaScript like this: let result=await amod.callC([\"bounce_balls_move\", param1]) If you are calling into C++, you need to use extern \"C\" like this in your C++ code: extern \"C\" int bounce_balls_move() {} Each C/C++ function that you wish to call from TypeScript/JavaScript needs to be exported in your wasm-ld settings like this: --export=bounce_balls_move Or like this in your source file: __attribute__((export_name(\"bounce_balls_move\"))) void bounce_balls_move() { ... See the Compiler Options . callC takes an array where: the first entry is the name of the C function in the wasm module to call and the next entries are a variable number of parameters to pass to the C function, of type: number - will be converted to int32 or float64 as appropriate string - converted to a pointer to module Memory where string is copied into ArrayBuffer - the array is loaded into module memory. If you need to pass the length, pass it as a separate parameter. Any modifications to the memory made by your C code will be reflected back into the JavaScript ArrayBuffer. URL - the url contents are loaded into module Memory, and two C parameters are generated - index (pointer) to the memory, and length callC returns the value returned by the C function that was called. As well int and float , string and structs (or blocks of memory) can be returned. More details can be found in examples/function-calls . The FFT example demonstrates passing a Float32Array view of an ArrayBuffer. Also see Key Concepts .","title":"callC"},{"location":"api/api-typescript/#divlog","text":"If stdio is set to twr_iodiv , you can use the divLog twrWasmModule/Async function like this: import {twrWasmModule} from \"twr-wasm\"; const mod = new twrWasmModule(); await mod.loadWasm(\"./tests.wasm\"); await mod.callC([\"tests\"]); mod.divLog(\"\\nsin() speed test\"); let sumA=0; const start=Date.now(); for (let i=0; i<2000000;i++) sumA=sumA+Math.sin(i); const endA=Date.now(); let sumB=await mod.callC([\"sin_test\"]); const endB=Date.now(); mod.divLog(\"sum A: \", sumA, \" in ms: \", endA-start); mod.divLog(\"sum B: \", sumB, \" in ms: \", endB-endA);","title":"divLog"},{"location":"api/api-typescript/#accessing-data-in-the-web-assembly-memory","text":"You probably will not need to use the twrWasmModule/Async functions in this section, as callC() will convert your parameters for you. But if you return or want to pass in more complicated structs, you might need to. The source in source/twr-wasm-ts/canvas.ts is an example of how these are used. async putString(sin:string, codePage=codePageUTF8) // returns index into WebAssembly.Memory async putU8(u8a:Uint8Array) // returns index into WebAssembly.Memory async putArrayBuffer(ab:ArrayBuffer) // returns index into WebAssembly.Memory async fetchAndPutURL(fnin:URL) // returns index into WebAssembly.Memory async malloc(size:number) // returns index in WebAssembly.Memory. stringToU8(sin:string, codePage=codePageUTF8) copyString(buffer:number, buffer_size:number, sin:string, codePage=codePageUTF8):void getLong(idx:number): number setLong(idx:number, value:number) getDouble(idx:number): number setDouble(idx:number, value:number) getShort(idx:number): number getString(strIndex:number, len?:number, codePage=codePageUTF8): string getU8Arr(idx:number): Uint8Array getU32Arr(idx:number): Uint32Array memory?:WebAssembly.Memory; mem8:Uint8Array; mem32:Uint32Array; memD:Float64Array;","title":"Accessing Data in the Web Assembly Memory"},{"location":"examples/examples-balls/","text":"Bouncing Balls - Web Assembly C++ Example This example uses Web Assembly, C++, and twr-wasm to bounce balls around your HTML page. It uses twr-wasm's 2D Draw API and a C++ Canvas class. View bouncing balls Source for balls The bouncing balls example demonstrates C++ Using the twr-wasm draw 2D APIs that match Javascript Canvas APIs. A C++ wrapper for the JavaScript Canvas class This example does not use libc++, which results in smaller code size. For an example that uses libc++ see tests-libcxx .","title":"balls"},{"location":"examples/examples-fft/","text":"FFT - Web Assembly C Example This example is a demo of integrating an existing FFT C library with Typescript/JavaScript/HTML using Web Assembly. The FFT C library is compiled into a wasm (Web Assembly) module, with the help of twr-wasm. The FFT wasm module is used by the HTML page to calculate the FFT. The FFT input and output is drawn to the web page using the normal JavaScript functions. The FFT library exposes APIs to process data, and doesn't use stdio. The FFT APIs use float32 arrays for complex-number input and output data, and a configuration struct. In the example I generate the input data by adding a 1K and 5K sine waves, call the kiss FFT API to perform the FFT on the generated sine waves, and then graph the input and output data using JavaScript Canvas. View running on the web View Source Code Here is part of the code. The rest can be found in the example. Fast Fourier transform (FFT)
      Input Signal



      FFT Output
      import {twrWasmModule} from \"twr-wasm\"; export async function fftDemo() { const mod=new twrWasmModule(); // load the kiss_fft C code as is, unmodified await mod.loadWasm('kiss_fft.wasm'); // kissFFTData stores and graphs the input and output data // in this example the fft has 1024 bins, and I am using a 48K sampling rate let fft=new kissFFTData(1024, 48000); fft.genSin(1000) fft.addSin(5000) fft.graphIn(\"c-input\"); // see kiss_fft README, but in summary you: (a) alloc config, (b) compute the FFT, (c) free the config // kiss_fft_alloc() returns a malloced structure. Pointers are numbers (index into wasm module memory) in JS land // //kiss_fft_cfg cfg = kiss_fft_alloc( nfft ,is_inverse_fft ,0,0 ); let cfg:number = await mod.callC([\"kiss_fft_alloc\", fft.nfft, 0, 0, 0 ]); // The FFT input and output data are C arrays of complex numbers. // typedef struct { // kiss_fft_scalar r; // kiss_fft_scalar i; // } kiss_fft_cpx; // // /* default is float */ // define kiss_fft_scalar float // So if the FFT data has 1024 bins, then 1024 * 2 floats (r & i) * 4 bytes per float are needed. // I use a JS Float32Array view on the ArrayBuffer to access the floats // When an arrayBuffer is passed in as an argument to mod.callC, // callC will malloc memory in the wasm module of a size that matches the array buffer, then // copy the arraybuffer into the malloc'd memory prior to the function call, // then copy the malloc'd memory contents back into the arrayBuffer post call. // The malloc'd memory is free'd post call. // void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); await mod.callC([\"kiss_fft\", cfg, fft.inArrayBuf, fft.outArrayBuf]); fft.graphOut(\"c-output\"); await mod.callC([\"free\", cfg]); // not much point to this since all the module memory is about to disappear }","title":"fft"},{"location":"examples/examples-helloworld/","text":"Hello World - Web Assembly C Example This example is an very simple twr-wasm program. It uses Web Assembly and C to print \"hello world\" to an HTML
      tag. Also see: Hello World - Step-by-Step C to WASM . View helloworld running live View helloworld Source","title":"hello world"},{"location":"examples/examples-libcxx/","text":"tests-libcxx - Web Assembly libc++ Example This simple smoke test for using libc++ with Web Assembly demonstrates a simple twr-wasm C++ program that uses libc++, and shows the needed makefile. view tests-libcxx running live View tests-libcxx Source Also see this Web Assembly program that uses libc++ with twr-wasm to implement a CLI console. tests-user Live tests-user Source","title":"libc++"},{"location":"examples/examples-maze/","text":"Maze - Web Assembly C Example This example is a port to wasm of a 20 year old Win32 C program with the help of twr-wasm 2D Draw APIs. View live maze here Source for maze This example (in winemu.c) uses the twr-wasm \"d2d\" (Draw 2D) APIs. These allow drawing onto an HTML canvas from C/C++. See the balls example for a C++ Canvas class. I have included the TypesScript below. You can see the C code in the examples/maze folder. This C is interesting in that it is a combination of blocking and non blocking functions. The CalcMaze() function is blocking when the \"slow draw\" flag is set. It uses Sleep() in this case. For this reason, I use twrWasmModuleAsync. The solve section uses repeated calls to SolveStep(), which works well with a JavaScript main loop. I used a javascript interval timer to make repeated calls to the C SolveStep(). If all the C code was structured this way, twrWasmModule could have been used (instead of the Async version) To port this code to twr-wasm I wrote a (very tiny) Win32 compatible API. It only implements the features needed to port maze, but it might be useful to use as a starting point for porting your Win32 code to the web. In the maze example, the two files are winemu.c and winemu.h. You use winemu.h to replace windows.h Maze import {twrWasmModuleAsync} from \"twr-wasm\"; export async function mazeRunner() { const amod=new twrWasmModuleAsync(); await amod.loadWasm('maze.wasm'); //void CalcMaze(HWND hWnd, LONG cell_size, LONG is_black_bg, LONG isd - slow draw) await amod.callC([\"CalcMaze\", 0, 7, 0, 1]); await amod.callC([\"SolveBegin\"]); let timer = setInterval(async ()=>{ let isdone=await amod.callC([\"SolveStep\", 0]); //SolveStep(hwnd)) if (isdone) clearInterval(timer); }, 50); }","title":"maze"},{"location":"examples/examples-more/","text":"More Web Assembly Examples Some other examples include: function-calls demos the different types of parameters that can be passed to a C function tests are the twr-wasm unit tests All Examples Live & Source The source for all of the examples is here on github All of the examples are available to view running live on the internet","title":"more"},{"location":"examples/examples-overview/","text":"Web Assembly C/C++ Examples These C and C++ examples demonstrate how to create different types of Web Assembly (wasm) programs with the twr-wasm library. These are good examples to use as starting points for your own wasm projects. These examples are a good place to learn how to configure clang and wasm-ld to compile and link C/C++ code for use with Web Assembly (wasm). Example Quick Links Click here to view C/C++ Web Assembly twr-wasm examples running live Click here to view source code and make files Examples Overview Each of these examples are designed to illustrate how to use a feature of twr-wasm. Name Description Link helloworld A very simple C wasm example to get you started helloworld stdio-div This simple C program demos inputting and printing characters to a div tag stdio-div stdio-canvas This simple C program demos writing and inputting from a tag that twr-wasm configures as a windowed \"mini-terminal\" stdio-canvas balls These fun Bouncing Balls are written in C++ and demo the 2D drawing APIs with a C++ Canvas wrapper class balls maze This is an old Win32 program ported to wasm and demos the 2D Draw APIs maze fft A demo of calling a C library to perform an FFT that is graphed in Typescript fft tests-libcxx Smoke test for libc++. Shows how to use libc++. tests-libcxx tests-user \"cli\" for tests using libc++ and tests-user more Demo of function calls, units tests more Building the Examples See Example Readme for more information on building and running the examples.","title":"Overview"},{"location":"examples/examples-stdio-canvas/","text":"stdio-canvas - Web Assembly 'terminal' C Example Print and input \"Hello World\" from a \"terminal\" window. A tiny Web Assembly C \"terminal\" can be created with input and output direct to a tag, and you can use it for character I/O with control over where the character appear in the terminal window. This example will move a string up or down in the terminal window when you press the u or d key. View stdio-canvas running live View stdio-canvas Source For another 'terminal' demo View tests-user #include #include #include #include \"twr-crt.h\" #include \"twr-wasm.h\" /* this twr-wasm C example draws a string in the middle of a windowed console, */ /* and allows the user to move the string up or down with the u or d keys */ /* see include/twr-io.h for available functions to draw chars to windowed console */ void show_str_centered(struct IoConsoleWindow* iow, int h, const char* str); void stdio_canvas() { struct IoConsoleWindow* iow=(struct IoConsoleWindow*)twr_get_stdio_con(); if (!(iow->con.header.type&IO_TYPE_WINDOW)) { // could also use assert here twr_conlog(\"error - expected window console\\n\"); return; } int h, c; const char* str=\"Hello World (press u or d)\"; const char* spc=\" \"; h=iow->display.height/2; while (1) { show_str_centered(iow, h, str); c=twr_getc32(); show_str_centered(iow, h, spc); // erase old string if (c=='u') { h=h-1; if (h<0) h=0; } if (c=='d') { h=h+1; if (h>=iow->display.height) h=iow->display.height-1; } } } void show_str_centered(struct IoConsoleWindow* iow, int h, const char* str) { int strlen=strlen(str); int x=(iow->display.width-strlen)/2; io_set_cursorxy(iow, x, h); io_putstr(&iow->con, str); } stdio-canvas example ","title":"stdio-canvas"},{"location":"examples/examples-stdio-div/","text":"stdio-div - Web Assembly stdio-to-div C Example This simple Web Assembly C program demos inputting and printing characters to a div tag. view stdio-div running live View stdio-div Source #include #include #include \"twr-crt.h\" void stdio_div() { char inbuf[64]; int i; printf(\"Square Calculator\\n\"); while (1) { printf(\"Enter an integer: \"); twr_mbgets(inbuf); i=atoi(inbuf); printf(\"%d squared is %d\\n\\n\",i,i*i); } } With an index.html like the following. This time we are using twrWasmModuleAsync which integrates blocking C code into JavaScript. twrWasmModuleAsync can also be used to receive key input from a
      or tag. stdio-div example
      Loading...
      ","title":"stdio-div"},{"location":"gettingstarted/compiler-opts/","text":"Compiling, Linking, and Memory Options This section described how to use clang to compile C/C++ code for Web Assembly, and how to link your files into a .wasm module. twr-wasm lets you use clang directly, without a wrapper. This section describes the needed clang compile options and the wasm-ld link options. You can also take a look at the example makefiles . C clang Compiler Options Targeting WASM When compiling C code with clang for use with wasm and twr-wasm, use these clang options: --target=wasm32 -nostdinc -nostdlib -isystem ../../include -isystem should point to the folder twr-wasm/include . The option line above uses a relative link to include that works if your project is a sub folder in the examples folder. If you installed using npm, then includes are at node_modules/twr-wasm/include (see the installation note on npm ). You will also need to link to twr.a (explained in the linking section below). C++ clang Compiler Options Targeting WASM When compiling C++ code with clang for use with wasm and twr-wasm, use these clang options: --target=wasm32 -fno-exceptions -fno-rtti -nostdlibinc -nostdinc -nostdlib -isystem ../../include You will also need to link to twr.a and libc++.a (explained in the linking section below). Be sure to adjust the path to twr.a , libc++.a , and the include folder as needed (see above note in the C section). wasm-ld Linker Options Use the wasm-ld linker directly with twr-wasm. All of the twr-wasm functions are staticly linked from the library lib-c/twr.a . There is also a version ( lib-c/twrd.a ) of twr-wasm library available with debug symbols. One of these two static libraries should be added to the list of files to link (normally this is twr.a ). Both versions are built with asserts enabled. twr.a is built with -O3 . twrd.a is built with -g -O0 . To use libc++ , link to libc++.a (see the tests-libcxx example makefile). C functions that you wish to call from JavaScript should either have an -export option passed to wasm-ld , or you can use the __attribute__((export_name(\"function_name\"))) option in your C function definition. All exported functions to JavaScript should be C linkage ( extern \"C\" if using C++). wasm-ld should also be passed the following options: If Using twrWasmModule: --no-entry --initial-memory= --max-memory= If Using twrWasmModuleAsync: --no-entry --shared-memory --no-check-features --initial-memory= --max-memory= Memory Options for Web Assembly You set the memory size for your module ( WebAssembly.Memory ) using wasm-ld options as follows (this examples sets your wasm memory to 1MB). The memory size should be a multiple of 64*1024 (64K) chunks. if using twrWasmModule : --initial-memory=1048576 --max-memory=1048576 If you are using twrWasmModuleAsync , shared memory must also be enabled. Like this: --shared-memory --no-check-features --initial-memory=1048576 --max-memory=1048576 See this production note on using shared memory . The memory is an export out of the .wasm into the JavaScript code. There is no support for automatically growing memory. You can change your C/C++ stack size from the default 64K with the following wasm-ld option. This example sets the stack at 128K -z stack-size=131072 You can print your module memory map, heap stats, and stack size using the function from C: void twr_mem_debug_stats(struct IoConsole* outcon); You can call it from Javascript with the output sent to the debug console (stderr) like this: twrWasmModule/Async.callC([\"twr_wasm_print_mem_debug_stats\"]) twrWasmModule and twrWasmModuleAsync expose malloc as an async function, as well as the Web Assembly Module memory as: async malloc(size:number); memory?:WebAssembly.Memory; mem8:Uint8Array; mem32:Uint32Array; memD:Float64Array; to call free() from JavaScript (you probably won't need to), you can use: twrWasmModule/Async.callC(\"twr_free\", index); // index to memory to free, as returned by malloc","title":"Compiler, Linker, Memory"},{"location":"gettingstarted/compiler-opts/#compiling-linking-and-memory-options","text":"This section described how to use clang to compile C/C++ code for Web Assembly, and how to link your files into a .wasm module. twr-wasm lets you use clang directly, without a wrapper. This section describes the needed clang compile options and the wasm-ld link options. You can also take a look at the example makefiles .","title":"Compiling, Linking, and Memory Options"},{"location":"gettingstarted/compiler-opts/#c-clang-compiler-options-targeting-wasm","text":"When compiling C code with clang for use with wasm and twr-wasm, use these clang options: --target=wasm32 -nostdinc -nostdlib -isystem ../../include -isystem should point to the folder twr-wasm/include . The option line above uses a relative link to include that works if your project is a sub folder in the examples folder. If you installed using npm, then includes are at node_modules/twr-wasm/include (see the installation note on npm ). You will also need to link to twr.a (explained in the linking section below).","title":"C clang Compiler Options Targeting WASM"},{"location":"gettingstarted/compiler-opts/#c-clang-compiler-options-targeting-wasm_1","text":"When compiling C++ code with clang for use with wasm and twr-wasm, use these clang options: --target=wasm32 -fno-exceptions -fno-rtti -nostdlibinc -nostdinc -nostdlib -isystem ../../include You will also need to link to twr.a and libc++.a (explained in the linking section below). Be sure to adjust the path to twr.a , libc++.a , and the include folder as needed (see above note in the C section).","title":"C++ clang Compiler Options Targeting WASM"},{"location":"gettingstarted/compiler-opts/#wasm-ld-linker-options","text":"Use the wasm-ld linker directly with twr-wasm. All of the twr-wasm functions are staticly linked from the library lib-c/twr.a . There is also a version ( lib-c/twrd.a ) of twr-wasm library available with debug symbols. One of these two static libraries should be added to the list of files to link (normally this is twr.a ). Both versions are built with asserts enabled. twr.a is built with -O3 . twrd.a is built with -g -O0 . To use libc++ , link to libc++.a (see the tests-libcxx example makefile). C functions that you wish to call from JavaScript should either have an -export option passed to wasm-ld , or you can use the __attribute__((export_name(\"function_name\"))) option in your C function definition. All exported functions to JavaScript should be C linkage ( extern \"C\" if using C++). wasm-ld should also be passed the following options: If Using twrWasmModule: --no-entry --initial-memory= --max-memory= If Using twrWasmModuleAsync: --no-entry --shared-memory --no-check-features --initial-memory= --max-memory=","title":"wasm-ld Linker Options"},{"location":"gettingstarted/compiler-opts/#memory-options-for-web-assembly","text":"You set the memory size for your module ( WebAssembly.Memory ) using wasm-ld options as follows (this examples sets your wasm memory to 1MB). The memory size should be a multiple of 64*1024 (64K) chunks. if using twrWasmModule : --initial-memory=1048576 --max-memory=1048576 If you are using twrWasmModuleAsync , shared memory must also be enabled. Like this: --shared-memory --no-check-features --initial-memory=1048576 --max-memory=1048576 See this production note on using shared memory . The memory is an export out of the .wasm into the JavaScript code. There is no support for automatically growing memory. You can change your C/C++ stack size from the default 64K with the following wasm-ld option. This example sets the stack at 128K -z stack-size=131072 You can print your module memory map, heap stats, and stack size using the function from C: void twr_mem_debug_stats(struct IoConsole* outcon); You can call it from Javascript with the output sent to the debug console (stderr) like this: twrWasmModule/Async.callC([\"twr_wasm_print_mem_debug_stats\"]) twrWasmModule and twrWasmModuleAsync expose malloc as an async function, as well as the Web Assembly Module memory as: async malloc(size:number); memory?:WebAssembly.Memory; mem8:Uint8Array; mem32:Uint32Array; memD:Float64Array; to call free() from JavaScript (you probably won't need to), you can use: twrWasmModule/Async.callC(\"twr_free\", index); // index to memory to free, as returned by malloc","title":"Memory Options for Web Assembly"},{"location":"gettingstarted/helloworld/","text":"Hello World - Step-by-Step C to WASM This section shows you step by step how to to create a C \"hello world\" program for Web Assembly (WASM) with twr-wasm, C, HTML, and JavaScript. You will learn how to: Create the helloworld.c C file Create the index.html HTML File Compile the helloworld.c code Link the helloworld.o and twr.a files to create a helloworld.wasm file Set the needed library and include paths to allow the twr-wasm libraries to be discovered Create an optional Makefile Execute the \"hello world\" program using a local web server or directly with VS Code and Chrome You can find all of the code for this section in the folder examples\\helloworld . Step 1: Create the C code Create a file helloworld.c #include void hello() { printf(\"hello world\\n\"); } Step 2: Create the HTML Create a file index.html Hello World
      This example uses Import Maps, which are used when not using a bundler like WebPack or Parcel. This can be a simpler and more clear debugging and development environment. The relative path in the importmap section should be updated to point to the location where you installed twr-wasm/lib-js . The path above is correct if your file is in an example subfolder. As another example, if you used git clone https://github.com/twiddlingbits/twr-wasm to create a folder named twr-wasm and you create your hello world project with a folder structure like this: my_project/ \u251c\u2500\u2500 twr-wasm/ \u2514\u2500\u2500 index.html \u2514\u2500\u2500 helloworld.c \u2514\u2500\u2500 helloworld.wasm Then you would use an Import Map code snippet like this: Step 3: Compile your C code to create your .wasm file clang --target=wasm32 -nostdinc -nostdlib -isystem ../../include -c helloworld.c -o helloworld.o wasm-ld helloworld.o ../../lib-c/twr.a -o helloworld.wasm --no-entry --initial-memory=131072 --max-memory=131072 --export=hello The path to twr.a and to include may need to be updated to match your installation. The above path is correct if your code is in an example subfolder. Alternately, if you had the folder structure described in Step 2: my_project/ \u251c\u2500\u2500 twr-wasm/ \u2514\u2500\u2500 index.html \u2514\u2500\u2500 helloworld.c \u2514\u2500\u2500 helloworld.wasm \u2514\u2500\u2500 Makefile You could use a MakeFile like this: CC := clang TWRCFLAGS := --target=wasm32 -nostdinc -nostdlib -isystem twr-wasm/include CFLAGS := -c -Wall -O3 $(TWRCFLAGS) CFLAGS_DEBUG := -c -Wall -g -O0 $(TWRCFLAGS) .PHONY: default default: helloworld.wasm helloworld.o: helloworld.c $(CC) $(CFLAGS) $< -o $@ helloworld.wasm: helloworld.o wasm-ld helloworld.o twr-wasm/lib-c/twr.a -o helloworld.wasm \\ --no-entry --initial-memory=131072 --max-memory=131072 \\ --export=hello Step 4: Load your web page The two easiest ways to load and execute your index.html web page locally are: Option A: Run a local web Server You can run a local server to view your helloworld program. Copy the file server.py from the examples folder to your project folder where your index.html resides. Execute with the shell command python server.py . Option B: VS Code launch.json Alternately, you can launch chrome without a local web server. Add an entry similar to the following to your VS code project's .vscode\\launch.json . Adjust the file and cwd lines to be correct for your project. { \"name\": \"hello\", \"type\": \"chrome\", \"request\": \"launch\", \"runtimeArgs\": [ \"--allow-file-access-from-files\", \"--autoplay-policy=no-user-gesture-required\", \"--enable-features=SharedArrayBuffer\" ], \"file\": \"${workspaceFolder}/examples/index.html\", \"cwd\": \"${workspaceFolder}/examples/\" } --autoplay-policy=no-user-gesture-required and --enable-features=SharedArrayBuffer are not required for this simple \"hello world\" example, but will be needed if you request user input or you are using twrWasModuleAsync. See live version Here is a link to the helloworld function running in the twiddlingbits.dev site. Next steps after hello world A good way to get your own code up and running is to copy one of the twr-wasm/examples , get it to build and run, then start modifying it. The example makefiles prove a more practical way to configure and execute clang and wasm-ld. \"Hello World\" uses the twr-wasm class twrWasmModule . If you wish to use C blocking functions, such as twr_getc32 or twr_sleep , you can use twrWasmModuleAsync . This square calculator example shows how to do this. If you wish to build an app that makes non-block calls into C, the balls example shows how to do this. The maze example uses a combination of blocking and non-blocking C functions.","title":"Create wasm C Hello World"},{"location":"gettingstarted/helloworld/#hello-world-step-by-step-c-to-wasm","text":"This section shows you step by step how to to create a C \"hello world\" program for Web Assembly (WASM) with twr-wasm, C, HTML, and JavaScript. You will learn how to: Create the helloworld.c C file Create the index.html HTML File Compile the helloworld.c code Link the helloworld.o and twr.a files to create a helloworld.wasm file Set the needed library and include paths to allow the twr-wasm libraries to be discovered Create an optional Makefile Execute the \"hello world\" program using a local web server or directly with VS Code and Chrome You can find all of the code for this section in the folder examples\\helloworld .","title":"Hello World - Step-by-Step C to WASM"},{"location":"gettingstarted/helloworld/#step-1-create-the-c-code","text":"Create a file helloworld.c #include void hello() { printf(\"hello world\\n\"); }","title":"Step 1: Create the C code"},{"location":"gettingstarted/helloworld/#step-2-create-the-html","text":"Create a file index.html Hello World
      This example uses Import Maps, which are used when not using a bundler like WebPack or Parcel. This can be a simpler and more clear debugging and development environment. The relative path in the importmap section should be updated to point to the location where you installed twr-wasm/lib-js . The path above is correct if your file is in an example subfolder. As another example, if you used git clone https://github.com/twiddlingbits/twr-wasm to create a folder named twr-wasm and you create your hello world project with a folder structure like this: my_project/ \u251c\u2500\u2500 twr-wasm/ \u2514\u2500\u2500 index.html \u2514\u2500\u2500 helloworld.c \u2514\u2500\u2500 helloworld.wasm Then you would use an Import Map code snippet like this: ","title":"Step 2: Create the HTML"},{"location":"gettingstarted/helloworld/#step-3-compile-your-c-code-to-create-your-wasm-file","text":"clang --target=wasm32 -nostdinc -nostdlib -isystem ../../include -c helloworld.c -o helloworld.o wasm-ld helloworld.o ../../lib-c/twr.a -o helloworld.wasm --no-entry --initial-memory=131072 --max-memory=131072 --export=hello The path to twr.a and to include may need to be updated to match your installation. The above path is correct if your code is in an example subfolder. Alternately, if you had the folder structure described in Step 2: my_project/ \u251c\u2500\u2500 twr-wasm/ \u2514\u2500\u2500 index.html \u2514\u2500\u2500 helloworld.c \u2514\u2500\u2500 helloworld.wasm \u2514\u2500\u2500 Makefile You could use a MakeFile like this: CC := clang TWRCFLAGS := --target=wasm32 -nostdinc -nostdlib -isystem twr-wasm/include CFLAGS := -c -Wall -O3 $(TWRCFLAGS) CFLAGS_DEBUG := -c -Wall -g -O0 $(TWRCFLAGS) .PHONY: default default: helloworld.wasm helloworld.o: helloworld.c $(CC) $(CFLAGS) $< -o $@ helloworld.wasm: helloworld.o wasm-ld helloworld.o twr-wasm/lib-c/twr.a -o helloworld.wasm \\ --no-entry --initial-memory=131072 --max-memory=131072 \\ --export=hello","title":"Step 3: Compile your C code to create your .wasm file"},{"location":"gettingstarted/helloworld/#step-4-load-your-web-page","text":"The two easiest ways to load and execute your index.html web page locally are:","title":"Step 4: Load your web page"},{"location":"gettingstarted/helloworld/#option-a-run-a-local-web-server","text":"You can run a local server to view your helloworld program. Copy the file server.py from the examples folder to your project folder where your index.html resides. Execute with the shell command python server.py .","title":"Option A: Run a local web Server"},{"location":"gettingstarted/helloworld/#option-b-vs-code-launchjson","text":"Alternately, you can launch chrome without a local web server. Add an entry similar to the following to your VS code project's .vscode\\launch.json . Adjust the file and cwd lines to be correct for your project. { \"name\": \"hello\", \"type\": \"chrome\", \"request\": \"launch\", \"runtimeArgs\": [ \"--allow-file-access-from-files\", \"--autoplay-policy=no-user-gesture-required\", \"--enable-features=SharedArrayBuffer\" ], \"file\": \"${workspaceFolder}/examples/index.html\", \"cwd\": \"${workspaceFolder}/examples/\" } --autoplay-policy=no-user-gesture-required and --enable-features=SharedArrayBuffer are not required for this simple \"hello world\" example, but will be needed if you request user input or you are using twrWasModuleAsync.","title":"Option B: VS Code launch.json"},{"location":"gettingstarted/helloworld/#see-live-version","text":"Here is a link to the helloworld function running in the twiddlingbits.dev site.","title":"See live version"},{"location":"gettingstarted/helloworld/#next-steps-after-hello-world","text":"A good way to get your own code up and running is to copy one of the twr-wasm/examples , get it to build and run, then start modifying it. The example makefiles prove a more practical way to configure and execute clang and wasm-ld. \"Hello World\" uses the twr-wasm class twrWasmModule . If you wish to use C blocking functions, such as twr_getc32 or twr_sleep , you can use twrWasmModuleAsync . This square calculator example shows how to do this. If you wish to build an app that makes non-block calls into C, the balls example shows how to do this. The maze example uses a combination of blocking and non-blocking C functions.","title":"Next steps after hello world"},{"location":"gettingstarted/installation/","text":"Installing twr-wasm This section describes how to install twr-wasm on your computer so that you can compile and link C/C++ to Web Assembly (WASM). npm install twr-wasm or git clone https://github.com/twiddlingbits/twr-wasm npm install will install everything necessary to build your software: built libraries (lib-js, lib-c), include. In addition the examples are installed. git clone will copy the built libraries (lib-js, lib-c), include, as well as the source, examples, doc source and VS Code settings. Either will work, although with different pros and cons -- see the below notes. After installation, Using twr-wasm can be a bit more complicated than using a package that is all JavaScript because your applications need to use twr-wasm JavaScript and C libraries. Installs for your C/C++ code To build C/C++ code for use in your wasm project, you will need to install clang and the wasm-ld linker. If you are using Windows, more details can be found at the end of the Building Source section. A Note on npm install After installation from npm, you will have a folder structure like this: node_modules\\ twr-wasm\\ examples\\ include\\ lib-c\\ lib-js\\ LICENSE package.json readme.md The JavaScript and TypeScript exports are in lib-js and should be found by VS Code, TypeScript or your bundler as usual when using a statement like import {twrWasmModule} from \"twr-wasm\" . The C library ( twr.a ) that you will need to link your C/C++ program to is found in the libs-c folder, and the C/C++ include files that you will need to use in your C/C++ program are found in the include folder. You will need to use paths to to these folders in your make file . All of the examples (in the examples folder above) have make files that use a relative path for twr.a and includes . These paths will work fine if your code is in an examples sub-folder as a peer to the other examples. But assuming your code is in your own project folder elsewhere, you will need to determine the correct path to twr.a and includes from your project's make file. Details on how to do this can be found in the leter sections: Hello World walkthrough and the Compiler and Linker Options section . There is no real downside to this installation method, except possibly: (1) it does not include source code (use git clone for that), and (b) the C libraries are buried inside your node_modules. A Note on git clone install This method of installation installs the complete code base, including source and build binaries. The primary downside to this method is that the JavaScript side of twr-wasm will not be placed in a node_modules folder. This will likely make it difficult for a bundler, TypeScript or VS Code to find the location of imports. There are a few solutions to this. In the provided hello world example, I use a package.json file with an alias entry. This syntax is supported by the Parcel bundler: { \"@parcel/resolver-default\": { \"packageExports\": true }, \"alias\": { \"twr-wasm\": \"../../lib-js/index.js\" }, \"dependencies\": { \"twr-wasm\": \"^2.0.0\" } } In the FFT example, I use the paths entry in the tsconfig.json file. This is found by TypeScript, VS Code and the Parcel bundler. \"paths\": { \"twr-wasm\": [\"./../../lib-js/index\"] } The paths for alias and paths shown above are correct for the included examples, but will likely need to be adjust for your project (see the following section \"Your First C Web Assembly Program\" ) As a alternative, you could install with both npm and git .","title":"Installation"},{"location":"gettingstarted/keyconcepts/","text":"Key Concepts - C/C++ WASM This section describes some key concepts that apply when using twr-wasm with your C/C++ Web Assembly code. Overview Your C/C++ Web Assembly project will consist of HTML (and related JavaScript or Typescript) and C or C++ source files that are compiled into a \".wasm\" binary file that is loaded as a Web Assembly module by your JavaScript or HTML. You will call C functions (or C++ with ' extern \"C\" ' linkage) in the .wasm module from your JavaScript. You can also call JavaScript functions from your C/C++ code, but this is less common. There is no direct equivalent to a C \"main\". Instead, a wasm module provides exported C functions that you can call from JavaScript/TypeScript. A wasm module is more like a runtime loaded dynamic library. On the JavaScript side you will use the twr-wasm JavaScript/TypeScript class twrWasmModule or twrWasmModuleAsync to load the .wasm module, and then call C functions in it (more details are in the TypeScript/Javascript API section ). You're C/C++ code can be non-blocking or blocking. Blocking means that it \"takes a long time\" to return. For example, if you want to send mouse events to C code, have the code process them then return, this would be non-blocking. Alternately, if your C code is a big loop that never returns, that would be very blocking. You can use the twr-wasm class twrWasmModuleAsync to execute blocking code from JavaScript. The example maze demonstrates both non-blocking and blocking C calls. Here are some examples of different types of C/C++ code: If you're C/C++ code does not have any direct user interface built in, it can do its calculations and return. The FFT is an example of this. If your C/C++ code uses a classic C \"UI\", where it gets keys from stdin and sends the results to stdout, you can direct stdin and stdout to a
      or tag. This is explained in the stdio section. Your C/C++ code could be sent events from JavaScript (such mouse, key, timer, or other). This is done by simply calling a C function with the events as parameters. The C/C++ code could then generate no output, could render to a
      or using stdio type C/C++ functions, or it could render to a using 2D drawing APIs that correspond to JavaScript canvas 2D draw operations. ( Balls ) is an example. Steps to integrate C code with JavaScript code Here are the general steps to integrate your C with your JavaScript: Compile your C code with clang and link with wasm-ld to create the .wasm file. On the JavaScript side you: Access twr-wasm \"ES\" modules in the normal way with import . Add a
      or to your HTML ( see stdio ) Use new twrWasmModule() , followed by a call to loadWasm() , then one or more callC() . Alternately, use twrWasmModuleAsync() -- which is interchangeable with twrWasmModule, but proxies through a worker thread, and adds blocking support, including blocking char input. Passing strings, arrayBuffers, etc The Web Assembly runtime provided in a browser will only pass numbers between C functions and JavaScript functions. This means if you use twrWasmModule.callC to call a C function, and pass integers or floats as arguments, they will work as expected. But if you pass a string, arrayBuffer, or the contents or a URL, twrWasmModule.callC will: allocate memory in your WebAssembly.Memory (using malloc). copy the string (or arrayBuffer or URL contents) into this memory. pass the memory index (aka a pointer in C land) to your C code. If URL contents are passed, your C function will receive a pointer to the data as the first argument, and a length as the second argument. If an arrayBuffer is passed to your C/C++ code, you probably will also need to pass in the length (unless it is already known). Upon return, the malloced memory is freed, and if the argument was an arrayBuffer, the appropriate contents in the wasm module memory are copied back into the arrayBuffer. This means that if your C code modifies a passed in block of arrayBuffer memory, the results will be reflected back into javaScript land. Some module functions (such as getString ) take or return an \"index:number\". Here index means an index into WebAssembly.Memory. As far as your C code is concerned, this is a pointer. Recalled that an arrayBuffer can be created and accessed using classes like Uint8Array or Float32Array . It is helpful to look at the examples .","title":"Key Concepts"},{"location":"gettingstarted/stdio/","text":"Stdio with C/C++ Web Assembly This section describes how you can direct C/C++ standard input or output to or from a div or canvas tag in a twr-wasm C/C++ wasm project. Use div or canvas tag Standard input and output can be directed to a
      or to a HTML tag. A
      is used for streamed character input and output, and a is used for sending characters or simple graphics to windowed input and output. In the windowed mode, the position of characters in a \"terminal\" style window can be specified. In windowed mode, you can use functions that output to stdout or input from stdin, as well as functions that use x,y coordinates, colors, etc.
      will be used for stdin and stdout if found. will be used for stdin and stdout if it exists and no div found. if neither of the above
      or is defined in your HTML, then stdout is sent to the debug console in your browser. And stdin is not available. If you use twrWasmModule options, a fourth null options is available. Unicode characters and symbols are supported in stdout and stdin and windowed i/o (see localization ). The window console also supports chunky (low res) graphics (each character cell can be used as a 2x3 graphic array). stderr streams to the browser's debug console. Examples Name View Live Link Source Link stdin and stdout to
      View square demo Source simple \"terminal\" via View hello world demo Source \"cli\" with a stdio View CLI demo using libc++ Source IO Console Docs stdin , stdout , and stderr are abstracted by a twr-wasm IO Consoles . UTF-8 or Windows-1252 Stdin and stdout can support UTF-8 or Windows-1252 character encodings (see localization ) stdout or stderr #include to access stdout , stdin , stderr , and FILE . FILE is supported for user input and output, and for stderr. File i/o (to a filesystem) is not currently supported. You can use these functions to output to the standard library defines stderr or stdout : fputc, putc, vfprintf, fprintf, fwrite You can use the IO Console functions referenced above to send to stdout and stderr . These functions go to stdout: printf, vprintf, puts, putchar Note that when characters are sent to the browser console using stderr they will not render to the console until a newline, return, or ASCII 03 (End-of-Text) is sent. For example: #include fprintf(stderr, \"hello over there in browser debug console land\\n\"); A more common method to send output to the debug console is to use twr_conlog . See General C API Section . stdin You can get characters from the standard C define stdin with these functions: io_mbgets - get a multibyte string from a console using the current locale character encoding twr_mbgets - similar to io_mbgets , except always gets a multibyte locale format string from stdin. io_mbgetc - get a multibyte character from an IoConsole (like stdin ) using the current locale character encoding getc (sames as fgetc ) - get a single byte from a FILE * (IoConsole) -- returning ASCII or extended ASCII (window-1252 encoding) io_getc32 - gets a 32 bit unicode code point from an IoConsole (which currently needs to be stdin) Reading from stdin is blocking, and so twrWasmModuleAsync must be used to receive keys from stdin. JavaScript needed for char input You should add a line like the following to your JavaScript for stdin to work: for twr_iodiv document.getElementById(\"twr_iodiv\").addEventListener(\"keydown\",(ev)=>{amod.keyDownDiv(ev)}); for twr_iocanvas document.getElementById(\"twr_iocanvas\").addEventListener(\"keydown\",(ev)=>{amod.keyDownCanvas(ev)}); You likely want a line like this to set the focus to the div or canvas so the user doesn't have to click on it: document.getElementById(\"twr_iocanvas\").focus(); You will also need to set the tabindex attribute in your div tag like this:
      See the stdio-div and stdio-canvas examples. Note that this section describes blocking input using stdin. As an alternative, you can send events (keyboard, mouse, timer, etc) to a non-blocking C function from JavaScript using callC . See the balls example.","title":"Stdio"},{"location":"more/building/","text":"Building the Source Source for twr-wasm The source can be found at: https://github.com/twiddlingbits/twr-wasm The main branch contains the latest release. The dev branch is work in progress. Tools needed You will need these core tools: NPM - package manager Typescript clang tool chain - for C/C++ code wasm-ld - to link the .wasm files wat2wasm - to compile web assembly (.wat) files of which I have a few GNU make git - to clone twr-wasm source, or to clone llvm, if you want to build libc++ In addition, you might need: VS Code - to use the debug launcher and build tasks Parcel v2 - to bundle the examples mkdocs - to build the documentation static web site python - mkdocs is built with python, and you need python to run server.py in examples CMake and ninja - to build llvm libc++ There is a deprecated gcc build that I used to use for testing, but now the tests are executed in wasm. To Build the Libraries (lib-c, lib-js) cd source make or on windows cd source mingw32-make To Build the Examples See examples/readme.md for more information. To build the examples, but not bundle them. cd examples sh buildall.sh To build bundles: sh buildbundles.sh To Build the docs In twr-wasm root folder: mkdocs build The destination of the build is found in the mkdocs.yml file ( site_dir: azure/docsite/ ). Usually the docs are built as part of building the static web site that hosts the docs and examples. This is accomplished using this shell script (found in examples folder): buildazure.sh To Build libc++ for wasm and twr-wasm See the instructions in the comments in the shell script source\\libcxx\\buildlibcxx.sh Installing clang and wasm-ld on Windows Here is how I installed the tools for windows: install MSYS2 1. https://www.msys2.org/ 2. After the install completes, run UCRT64 terminal by clicking on the MSYS2 UCRT64 in the Start menu 3. pacman -Syuu install gcc using MSYS2 UCRT64 1. Use MSYS2 UCRT64 terminal (per above) 1. pacman -S mingw-w64-ucrt-x86_64-toolchain install clang and wasm-ld using MSYS2 UCRT64 2. Use MSYS2 UCRT64 (per above) 1. pacman -S mingw-w64-ucrt-x86_64-clang 2. pacman -S mingw-w64-x86_64-lld update PATH env variable using the windows control panel (search for path) 2. added C:\\msys64\\ucrt64\\bin 3. added C:\\msys64\\mingw64\\bin 4. added C:\\msys64\\usr\\bin (for sh.exe used by mingw32-make) wabt tools: can be found here https://github.com/WebAssembly/wabt/releases","title":"Building the Source"},{"location":"more/debugging/","text":"Debugging Web Assembly This section describes some tips for debugging your Web Assembly (asm) program. Debug and Release libraries There are release (twr.a) and debug (twrd.a) versions of the twr-wasm C library. See the examples for use of both. The \"debug\" version has debug symbols enabled and is built with -O0 . The \"release\" version has no debug symbols and optimization is set to -O3 . Both have asserts enabled. In general, you should use the \"release\" version unless you wish to step through the twr-wasm source -- in which case use the \"debug\" version. libc++.a is not built with debug symbols. Source Level Debugging Web Assembly C/C++ In order to enable C/C++ source debugging with wasm and clang, do the following: Use Chrome Install the Chrome extension: C/C++ DevTools Support (DWARF) ( https://chromewebstore.google.com/detail/pdcpmagijalfljmkmjngeonclgbbannb ) Use the clang compile flag -g to add debug annotation to your object files You will may want to turn off optimization to allow the debugger to have a bit more logical behavior (remove the -O flag or set to -O0) You may want to use the version of the twr-wasm C library that has debug symbols enabled (twrd.a). Only if you want to step into the twrd.a source. You need to serve your files with a (likely local) web server. For example, 'python server.py' is provided. 'server.py' can be found in the examples root folder. Note that your local server needs to enable SharedArrayBuffers -- see the server.py example. your code can be bundled or unbundled, but you need to ensure that the web server/browser can find the source code also see Example Readme Useful twr-wasm Debug Functions Use twr_conlog to print 'printf' style to the JavaScript console from C (reference is elsewhere in this doc.) #include \"twr-wasm.h\" twr_conlog(\"hello 99 in hex: %x\",99); Use twrWasmModule.divLog() to print to a div inside JavaScript code (reference is elsewhere in this doc.) Testing Web Assembly Without a Web Server Note: If you use this technique, you will not be able to get the c/C++ DevTool chrome extension to run, and so source level debugging won't work. You can execute and debug JavaScript with wasm from local files without an HTTP server. It might be helpful to download the twr-wasm source code from github when you do this (so you can step through the twr-wasm typescript code as needed). See the examples and Example Readme for more detail on how this works. In general, you will need to add a clip of code similar to this to your HTML: Make sure the paths are correct. You will need to set the following flags when running chrome from the shell (the first is only strictly required if using twrWasmModuleAsync): --enable-features=SharedArrayBuffer --allow-file-access-from-files You can create a launch.json entry similar to this: { \"name\": \"Examples\", \"type\": \"chrome\", \"request\": \"launch\", \"runtimeArgs\": [\"--allow-file-access-from-files\",\"--autoplay-policy=no-user-gesture-required\",\"--enable-features=SharedArrayBuffer\"], \"file\": \"${workspaceFolder}/examples/index.html\", \"cwd\": \"${workspaceFolder}/examples/\" }","title":"Debugging WASM"},{"location":"more/production/","text":"Production Important Production Note twr-wasm class twrWasmModuleAsync uses SharedArrayBuffers, and there are special CORS headers needed for these, that are not widely enabled by default on web servers. server.py or staticwebapp.config.json shows which headers to set (also see the SharedArrayBuffer documentation online).","title":"Production"},{"location":"more/wasm-problem/","text":"WASM Runtime Limitations HTML browsers can load a Web Assembly module, and execute it's bytecode in a browser virtual machine. You compile your code using clang with the target code format being web assembly (wasm) byte code. There are a few issues that one immediately encounters trying to execute code that is more complicated than squaring a number. The first is that there is no C/C++ runtime support native to a Web Assembly module. That is, no malloc or printf or similar functions. Even beyond than that, there are missing compiler support functions. That is, clang code generation will produce calls for compiler support routines needed for floating point, memcpy, and the like. This code is usually handled behind the scenes for you. For example, gcc will link to \"libgcc\" automatically. clang uses \"compile-rt\". This doesn't happen with Web Assembly compiles (unless you use emscripten or twr-wasm). The second problem is that all the function calls between your wasm module and your javascript are limited to parameters and return values that are numbers (integer and float). No strings, arrays, struct pointers, etc. The third problem is that legacy C code or games often block, and when written this way they don't naturally integrate with the JavaScript asynchronous programming model. twr-wasm is a static C library (twr.a) that you can link to your clang C/C++ code, as well as a set of JavaScript/Typescript modules that solve these issues.","title":"WASM Runtime Limitations"}]} \ No newline at end of file diff --git a/azure/docsite/sitemap.xml b/azure/docsite/sitemap.xml index e52422fe..21279296 100644 --- a/azure/docsite/sitemap.xml +++ b/azure/docsite/sitemap.xml @@ -2,132 +2,132 @@ https://twiddlingbits.dev/docsite/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/api/api-c-con/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/api/api-c-d2d/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/api/api-c-general/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/api/api-c-stdlib/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/api/api-libc%2B%2B/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/api/api-localization/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/api/api-typescript/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/examples/examples-balls/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/examples/examples-fft/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/examples/examples-helloworld/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/examples/examples-libcxx/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/examples/examples-maze/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/examples/examples-more/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/examples/examples-overview/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/examples/examples-stdio-canvas/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/examples/examples-stdio-div/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/gettingstarted/compiler-opts/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/gettingstarted/helloworld/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/gettingstarted/installation/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/gettingstarted/keyconcepts/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/gettingstarted/stdio/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/more/building/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/more/debugging/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/more/production/ - 2024-06-19 + 2024-06-20 daily https://twiddlingbits.dev/docsite/more/wasm-problem/ - 2024-06-19 + 2024-06-20 daily \ No newline at end of file diff --git a/azure/docsite/sitemap.xml.gz b/azure/docsite/sitemap.xml.gz index 888c03468a73fa97dc90b61ccf2b37dbe5d1c086..d1f027e9c1d18d5f408cca49ed3ed95e3b03a25b 100644 GIT binary patch literal 425 zcmV;a0apGWiwFp}oOEUa|8r?{Wo=<_E_iKh0M*xDi<~eJ0Py$w6pPTu7%Qc;#r5DG z?h~{hASSbJ=$NFLS>3%)-{>93a*u_A6BJ_@#~)(;b&uBx4>M%)F&wMUbyFQ6*ywy1 zkJYcA&+1$C*gtfaj0Air!GVs|nK}K?dRdm5Ji}xX)iIBn?77^KerwcC{k`fR4yCLK zUTa(FFxr02LM06^-Z?BU96VF)VAd|$HHGf<8h8JgA)cb^+ot`Zny;#DO2}K=U6?(a zFv2OrpWYddw@%-+yn6II=-+52`Sny**%)L%UF&2(M+lG&%D@trh(Ut2Fzu)IsT?A- z(HitGhP{mb#kT}xvroKdEnLl%5a_+427^el$fuLAZ+r&CxWtT3mU|sBu2)&+$-ICt zam>QRu`C#84~r~ynW=qL)`Z!RM7i_xp4lTXmv&;48JxCpN**Drn3x2)WsKDy&_0wJ z;_eqqAK1U)R(4MoWc?vqZ``wYn^1;}$8{IKd#HoqGL90YDMxp)d+%c#bul!l;vEpC T|Bu}+1l<1xd+D=vPZ9tCwU*WN literal 426 zcmV;b0agAViwFqkFmh%B|8r?{Wo=<_E_iKh0M*ycYU3~v0N{I{A{cs6E{+2| z^a;8TAWIWRbS$ZwiJkQ6S9VJYJuWPGgpFk}9)B3?uQ^->+>DUP$FQ#+>TR`wV59S) z-&cQLp4G4F(B3uYj0C(X!GZSGi8=k&dYY!1Ji}lT)iL*)?5W(4{%q9S`mt*7Hl@r7 zK59#8Fxqy`LM07P-Z?BU>^xKLVAL+!IfZWY9C!PeAs(V@ciY_$wf(6c9!tn)+fA4~ znb5;A!&~c&$7`c+T0T7b3-oU^ll*)tt85H1pl;`6Kzj&~4a&e0mxxY+wJ`1d?x`Fi zw9y*$?}ojM{>9e>WV27aW-VOIkPzsrqB?^}vdG7yuy1?<#5l!_PL_KfF)kNb=E1y! zFmcSn#IYlNp@0aY!B^tC*Msxn+#i-_Smk z8sh2~OW)Y9a4owh3$p%@r8lnGyG$tE+2g#6Up>@8ckX)$(v+h++qL(xg*q7;RPlBQ U!~e%F7Xoho0)5&9lTQ)=0Bg3@*Z=?k diff --git a/azure/examples/balls/balls-a.wasm b/azure/examples/balls/balls-a.wasm index 9fec7d4ae1ba4f1081d3b7698ee32f2a7c76e391..eafb34c4500e68fd56e1b5909aeee4ae642b6a8d 100644 GIT binary patch delta 4174 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 BjO73T diff --git a/azure/examples/balls/balls.wasm b/azure/examples/balls/balls.wasm index 08c732effb77e372e0c3c7f62f35b08d81b14a9a..d7ea0e1245441aacffb604e1febb5e6d2f2bd859 100644 GIT binary patch delta 4104 zcma)94Nz3q6~6Z_%Nkd7Au94CdAnv6m0fpH7QqmCDj-@E6;l#5x)r2BKoCTXkp&YI zOjN*wEmUKuh>?g$yBJAjTH;S)6Pz#^YjMVQn3zr*HB)0U$xM@uJ@>x%cKMmk$jrWX z&pF@uefOSw_`HcdY+{{nGdk!!&Y~&p@qVmZNNGP9^f`183iOfq+^_dc?ELM%DiTCw zBGW`72>Ag-21d{>m>(ETJHZ_oNgqIEV3?=7qpFISnf!{G>XIcYU+hFWUw(v&1j#=L zQeq1A!7!?O7IC!1)X+7q9Fn^d(IH2$8Zmfi^ON! zxP2jAJSS6q6+&6EOrlwrH#sPcp|oZ~k)?-AWn!i*St7D=DNkM^7c4A6*DpjA+@^4S z3i1aa-jop~6pRR>F4oHt#)+s9jiz;FazC6fxv;LcOq=nU6nx}KVI+UH4)H#WJ0ui- z3SRwxWc9Qcz74tN=vLh4yO>xRC2EWoo|eeO#qhy%Q9vFJ^4@#$rjFLZrO@Kgj}KzD za@||}d5fAZ^W=^4`;a~*+wk`Tocp8q^b|d%KYBaDGAaEK9))Lm>V(9p!Z9Os(Aa`0 z^6bwlCIw`!W>Hk(7>DqJ$RCm-Ik3#aT&$V%u%uM(CCgE}zE%Vzv=bF=Ze764jF*$R zJnW=uiOITh7dx#|L}HjS-!m|KB?D7bh z2X_JDcwCBWU71AlIVm!JS40VrIUQ`Amtp(T>E^;1<64mEXcgss*F* zpE?SCkrAGIODAQHZopwi*D6{TJhHq5Rlo{KpU(gL2Tlg5d z>M$H{L5p%7*rjGxa{~IMbovOw&5Kd|qSJTdq3;hs<`f@*ykp&t?ZvJVBB^ zUKfp3Rbi6c1AjBeJgt(+a{F1W5c#IRh(m)qXphL}!Dg97+acQ$PyY>d7B@D-hn6&a zCQi#T{I^Ys>d3ShQQz{kD`DlrdM1w2v$}u)&tKc&iL7F&Q3Ls7glELhUywQf8h2piQocX>1Qo5~gp7+!z)!J@DPV54&)c!! z2ga%oz`M_u@K^Z4sr;3&@Hl@tSBAl-$<`AsMdG?DsTQ*s5x{vSO=3eyzN0sQWuV;DWZix2jEBo?AU+Sqhdr~VL!XkC`bc+~lK+Jt~Rb-0v> z>~FC|#;?f5nJE5@-!mxo_gB=e5n^npGVtpG#l61vOXS-p_i=3pirabbm&khAq4imG z#6#yjmCC0Y6>Z5cRh3OB{hVJ7Xj^NhJV=qYz+lJ4^CSQID7?D%Ds6%E=k^BmiCect zRH7E>#!0ZyZGeL8F+qoM9>S(BBy~`o{W{eCyz6oC-s4ax;p9*Q@yA8XN&U9Ugq!|ixr+BI~wu>E8ma@pt#eVWf`kfjn?q|LwyHwzQ zh3r&GjGIf_Rf{<7)u~Gy%MPeZ1k@_o$YU{hGq&L+oj7nMfMcrT2)hDmY)O z%)jzuqm;^mYF9X$C5tw#Ab8MpPy7AK(&yH~WLC&0scR~RpFdiL2XR1UFiD40A5v+2<9u+`mxes14F6Ty zj$^xOw3W|oN{T*NkC2J4Ypc*;fmIcGH zqBh-~>b&yVypnU`)yDP+t-Yoy9Tm zNl9%`9)@i1q{jhI{+wU&5nZ8v-RssH}VWS!Ue= zjW3^t6}v4@Jbo_9`V%lQ8RUE43S delta 4082 zcma)9eNa@_6~Ff`u-Fw{2#9=0-mY22k6m{~9*A0bQ9!gP8Z;!vn3b;-0YUHsjVwel z8dpWnVnI7Z;98s<{k3&zl5+6NV(iTKWOZ7uep&# z5QQi-g9xD9gv77}>Vx#KWZDAmuta(j8p7f{Z9R>R#KM%fEYy%GQRPT4;&SCj>_`wE z7Eod;Y9EB!2BBXJ?s#aBvvm;i1rdxf#zu7TF<1@dRt(w(8O8+6Y=tp36o=~_nTXG> zkL=6=I<*QzD9K0Z(2cpIX^WL$7dAaGT>p zv(SDK(#&~DqJs%ZRA!x=VT#5M$tZ28Q+nZjvy64UV=ltyoXFPagh=@m1M&kLcT_Aq zja>GBdg>9x7Hp*<5h7eSg7P+Whaa$X2Y^3ivpJ!$z!F=9&?m)r$EBsI_-Q2%_7 zar+5WRJ`DjI@!bb;HH#I??b$09=cz**i2_WKsUx#emDdBEDnqMAsfoi6-H28K~iX% zAsMTx(In**+_g-7L4%n}%Q?Le<>p&r(O@6cBT5_Ct&?$e6$4^De7o7b=ZT_!a{VZT~rzXKR zIT;?#2oBnv`ecYdn1IgjObZMeG@HLWeFTm7@%3xPg9X>JX!AACziu1cnE9Hcjk|G+ zvs3C(XGw?J0ar|?IBJlrwq(`;uVhU8*(GkyHjNT0ouYpLp44FrrR-S*`!mK{R6z`g zqf+%~Hb)ksj_4$qXT{LJ!h~7*>8E)B6Zi7@(JfH2#uGm7G6P@5GE>Q1w%gw`>j`83 z-2)%~w1&Up=Z@pAnRAcvmupEJe3jV*wV87?=>ICyF8JK_(Xuu;J11qdTP#)n*n&-oD8Vh3 zDEJk*J0IQO@N)*;!Tl9`?-Fj@P?ZjTJfOQTu>BI{(#dAt+llT2eD9aYYl>6fXOYT> z&i7QR>}*qeOF^&J*^J&#_|bsc`ew?*h_nR>HmF_ES z%wxW(m`qqo^E>>j$D6{5(gHJzr!2h27ddW1+tu07r@7)A&-feS zR?`o&OP-JVPK_oR%-7YCG(u&`SkFD(EVHL-QxW;e?9VFXBmG+Q;C$v&(#Iz*CcImP zEgHmebFWv065jUyrHSLU?4Mc_34hmwX&USIXv%2*OR%|1QzRMWv1a{MYoIDJ>(u<0 z__9$;WkrRP+{`k?Hmx#v;dY9flUlfLt#F(o*d7bvS3t~$Q#<)JN>QojhEkC!jwVAT zzh+)g1Mu5^ui6ZRwK9cO@|)CYjlQ%78!h&PqSa8s-Qcjayh zj*5Rna^-ATTR8!$t0uz1$~B>-?uyzHcvLwL(yP)TYC{y9uIhs2>s;VnR|hp!Hu$E- z2*&Et5Xs>pu(W0j?5&Q6&uXT^AFA!ZYMPm?40hI}An#E4^kS0r(z1CAplN*{vq>+D#Yge6(Lq@dsxg5}7v&zwn;ZMIF5;Cy{7Oxu<^!m+#{ w+n!D&7gTLiz`t$r=r)JRM;i$t6o0d0A+jNE0=Yeg5c`ndFq?l#!--M<1Dbm%`~Uy| diff --git a/azure/examples/dist/balls/balls-a.wasm b/azure/examples/dist/balls/balls-a.wasm index 9fec7d4ae1ba4f1081d3b7698ee32f2a7c76e391..eafb34c4500e68fd56e1b5909aeee4ae642b6a8d 100644 GIT binary patch delta 4174 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 BjO73T diff --git a/azure/examples/dist/balls/balls.wasm b/azure/examples/dist/balls/balls.wasm index 08c732effb77e372e0c3c7f62f35b08d81b14a9a..d7ea0e1245441aacffb604e1febb5e6d2f2bd859 100644 GIT binary patch delta 4104 zcma)94Nz3q6~6Z_%Nkd7Au94CdAnv6m0fpH7QqmCDj-@E6;l#5x)r2BKoCTXkp&YI zOjN*wEmUKuh>?g$yBJAjTH;S)6Pz#^YjMVQn3zr*HB)0U$xM@uJ@>x%cKMmk$jrWX z&pF@uefOSw_`HcdY+{{nGdk!!&Y~&p@qVmZNNGP9^f`183iOfq+^_dc?ELM%DiTCw zBGW`72>Ag-21d{>m>(ETJHZ_oNgqIEV3?=7qpFISnf!{G>XIcYU+hFWUw(v&1j#=L zQeq1A!7!?O7IC!1)X+7q9Fn^d(IH2$8Zmfi^ON! zxP2jAJSS6q6+&6EOrlwrH#sPcp|oZ~k)?-AWn!i*St7D=DNkM^7c4A6*DpjA+@^4S z3i1aa-jop~6pRR>F4oHt#)+s9jiz;FazC6fxv;LcOq=nU6nx}KVI+UH4)H#WJ0ui- z3SRwxWc9Qcz74tN=vLh4yO>xRC2EWoo|eeO#qhy%Q9vFJ^4@#$rjFLZrO@Kgj}KzD za@||}d5fAZ^W=^4`;a~*+wk`Tocp8q^b|d%KYBaDGAaEK9))Lm>V(9p!Z9Os(Aa`0 z^6bwlCIw`!W>Hk(7>DqJ$RCm-Ik3#aT&$V%u%uM(CCgE}zE%Vzv=bF=Ze764jF*$R zJnW=uiOITh7dx#|L}HjS-!m|KB?D7bh z2X_JDcwCBWU71AlIVm!JS40VrIUQ`Amtp(T>E^;1<64mEXcgss*F* zpE?SCkrAGIODAQHZopwi*D6{TJhHq5Rlo{KpU(gL2Tlg5d z>M$H{L5p%7*rjGxa{~IMbovOw&5Kd|qSJTdq3;hs<`f@*ykp&t?ZvJVBB^ zUKfp3Rbi6c1AjBeJgt(+a{F1W5c#IRh(m)qXphL}!Dg97+acQ$PyY>d7B@D-hn6&a zCQi#T{I^Ys>d3ShQQz{kD`DlrdM1w2v$}u)&tKc&iL7F&Q3Ls7glELhUywQf8h2piQocX>1Qo5~gp7+!z)!J@DPV54&)c!! z2ga%oz`M_u@K^Z4sr;3&@Hl@tSBAl-$<`AsMdG?DsTQ*s5x{vSO=3eyzN0sQWuV;DWZix2jEBo?AU+Sqhdr~VL!XkC`bc+~lK+Jt~Rb-0v> z>~FC|#;?f5nJE5@-!mxo_gB=e5n^npGVtpG#l61vOXS-p_i=3pirabbm&khAq4imG z#6#yjmCC0Y6>Z5cRh3OB{hVJ7Xj^NhJV=qYz+lJ4^CSQID7?D%Ds6%E=k^BmiCect zRH7E>#!0ZyZGeL8F+qoM9>S(BBy~`o{W{eCyz6oC-s4ax;p9*Q@yA8XN&U9Ugq!|ixr+BI~wu>E8ma@pt#eVWf`kfjn?q|LwyHwzQ zh3r&GjGIf_Rf{<7)u~Gy%MPeZ1k@_o$YU{hGq&L+oj7nMfMcrT2)hDmY)O z%)jzuqm;^mYF9X$C5tw#Ab8MpPy7AK(&yH~WLC&0scR~RpFdiL2XR1UFiD40A5v+2<9u+`mxes14F6Ty zj$^xOw3W|oN{T*NkC2J4Ypc*;fmIcGH zqBh-~>b&yVypnU`)yDP+t-Yoy9Tm zNl9%`9)@i1q{jhI{+wU&5nZ8v-RssH}VWS!Ue= zjW3^t6}v4@Jbo_9`V%lQ8RUE43S delta 4082 zcma)9eNa@_6~Ff`u-Fw{2#9=0-mY22k6m{~9*A0bQ9!gP8Z;!vn3b;-0YUHsjVwel z8dpWnVnI7Z;98s<{k3&zl5+6NV(iTKWOZ7uep&# z5QQi-g9xD9gv77}>Vx#KWZDAmuta(j8p7f{Z9R>R#KM%fEYy%GQRPT4;&SCj>_`wE z7Eod;Y9EB!2BBXJ?s#aBvvm;i1rdxf#zu7TF<1@dRt(w(8O8+6Y=tp36o=~_nTXG> zkL=6=I<*QzD9K0Z(2cpIX^WL$7dAaGT>p zv(SDK(#&~DqJs%ZRA!x=VT#5M$tZ28Q+nZjvy64UV=ltyoXFPagh=@m1M&kLcT_Aq zja>GBdg>9x7Hp*<5h7eSg7P+Whaa$X2Y^3ivpJ!$z!F=9&?m)r$EBsI_-Q2%_7 zar+5WRJ`DjI@!bb;HH#I??b$09=cz**i2_WKsUx#emDdBEDnqMAsfoi6-H28K~iX% zAsMTx(In**+_g-7L4%n}%Q?Le<>p&r(O@6cBT5_Ct&?$e6$4^De7o7b=ZT_!a{VZT~rzXKR zIT;?#2oBnv`ecYdn1IgjObZMeG@HLWeFTm7@%3xPg9X>JX!AACziu1cnE9Hcjk|G+ zvs3C(XGw?J0ar|?IBJlrwq(`;uVhU8*(GkyHjNT0ouYpLp44FrrR-S*`!mK{R6z`g zqf+%~Hb)ksj_4$qXT{LJ!h~7*>8E)B6Zi7@(JfH2#uGm7G6P@5GE>Q1w%gw`>j`83 z-2)%~w1&Up=Z@pAnRAcvmupEJe3jV*wV87?=>ICyF8JK_(Xuu;J11qdTP#)n*n&-oD8Vh3 zDEJk*J0IQO@N)*;!Tl9`?-Fj@P?ZjTJfOQTu>BI{(#dAt+llT2eD9aYYl>6fXOYT> z&i7QR>}*qeOF^&J*^J&#_|bsc`ew?*h_nR>HmF_ES z%wxW(m`qqo^E>>j$D6{5(gHJzr!2h27ddW1+tu07r@7)A&-feS zR?`o&OP-JVPK_oR%-7YCG(u&`SkFD(EVHL-QxW;e?9VFXBmG+Q;C$v&(#Iz*CcImP zEgHmebFWv065jUyrHSLU?4Mc_34hmwX&USIXv%2*OR%|1QzRMWv1a{MYoIDJ>(u<0 z__9$;WkrRP+{`k?Hmx#v;dY9flUlfLt#F(o*d7bvS3t~$Q#<)JN>QojhEkC!jwVAT zzh+)g1Mu5^ui6ZRwK9cO@|)CYjlQ%78!h&PqSa8s-Qcjayh zj*5Rna^-ATTR8!$t0uz1$~B>-?uyzHcvLwL(yP)TYC{y9uIhs2>s;VnR|hp!Hu$E- z2*&Et5Xs>pu(W0j?5&Q6&uXT^AFA!ZYMPm?40hI}An#E4^kS0r(z1CAplN*{vq>+D#Yge6(Lq@dsxg5}7v&zwn;ZMIF5;Cy{7Oxu<^!m+#{ w+n!D&7gTLiz`t$r=r)JRM;i$t6o0d0A+jNE0=Yeg5c`ndFq?l#!--M<1Dbm%`~Uy| diff --git a/azure/examples/dist/balls/index.html b/azure/examples/dist/balls/index.html index e03d18d2..4e2f78e8 100644 --- a/azure/examples/dist/balls/index.html +++ b/azure/examples/dist/balls/index.html @@ -4,4 +4,4 @@ "twr-wasm": "../../lib-js/index.js" } } -

      Bouncing Balls Demo

      Web Assembly with twr-wasm


      \ No newline at end of file +

      Bouncing Balls Demo

      Web Assembly with twr-wasm


      \ No newline at end of file diff --git a/azure/examples/dist/fft/index.html b/azure/examples/dist/fft/index.html index 1ac4bea7..62e764c1 100644 --- a/azure/examples/dist/fft/index.html +++ b/azure/examples/dist/fft/index.html @@ -1,4 +1,4 @@ -Fast Fourier transform (FFT)Maze Maze stdio-canvas example stdio-canvas example Interactive User Tests Interactive User Tests Tests
      Tests