github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/examples/allocation/tinygo/testdata/greet.go (about)

     1  package main
     2  
     3  // #include <stdlib.h>
     4  import "C"
     5  
     6  import (
     7  	"fmt"
     8  	"runtime"
     9  	"unsafe"
    10  )
    11  
    12  // main is required for TinyGo to compile to Wasm.
    13  func main() {}
    14  
    15  // greet prints a greeting to the console.
    16  func greet(name string) {
    17  	log(fmt.Sprint("wasm >> ", greeting(name)))
    18  }
    19  
    20  // log a message to the console using _log.
    21  func log(message string) {
    22  	ptr, size := stringToPtr(message)
    23  	_log(ptr, size)
    24  	runtime.KeepAlive(message) // keep message alive until ptr is no longer needed.
    25  }
    26  
    27  // _log is a WebAssembly import which prints a string (linear memory offset,
    28  // byteCount) to the console.
    29  //
    30  //go:wasmimport env log
    31  func _log(ptr, size uint32)
    32  
    33  // greeting gets a greeting for the name.
    34  func greeting(name string) string {
    35  	return fmt.Sprint("Hello, ", name, "!")
    36  }
    37  
    38  // _greet is a WebAssembly export that accepts a string pointer (linear memory
    39  // offset) and calls greet.
    40  //
    41  //export greet
    42  func _greet(ptr, size uint32) {
    43  	name := ptrToString(ptr, size)
    44  	greet(name)
    45  }
    46  
    47  // _greeting is a WebAssembly export that accepts a string pointer (linear memory
    48  // offset) and returns a pointer/size pair packed into a uint64.
    49  //
    50  // Note: This uses a uint64 instead of two result values for compatibility with
    51  // WebAssembly 1.0.
    52  //
    53  //export greeting
    54  func _greeting(ptr, size uint32) (ptrSize uint64) {
    55  	name := ptrToString(ptr, size)
    56  	g := greeting(name)
    57  	ptr, size = stringToLeakedPtr(g)
    58  	return (uint64(ptr) << uint64(32)) | uint64(size)
    59  }
    60  
    61  // ptrToString returns a string from WebAssembly compatible numeric types
    62  // representing its pointer and length.
    63  func ptrToString(ptr uint32, size uint32) string {
    64  	return unsafe.String((*byte)(unsafe.Pointer(uintptr(ptr))), size)
    65  }
    66  
    67  // stringToPtr returns a pointer and size pair for the given string in a way
    68  // compatible with WebAssembly numeric types.
    69  // The returned pointer aliases the string hence the string must be kept alive
    70  // until ptr is no longer needed.
    71  func stringToPtr(s string) (uint32, uint32) {
    72  	ptr := unsafe.Pointer(unsafe.StringData(s))
    73  	return uint32(uintptr(ptr)), uint32(len(s))
    74  }
    75  
    76  // stringToLeakedPtr returns a pointer and size pair for the given string in a way
    77  // compatible with WebAssembly numeric types.
    78  // The pointer is not automatically managed by TinyGo hence it must be freed by the host.
    79  func stringToLeakedPtr(s string) (uint32, uint32) {
    80  	size := C.ulong(len(s))
    81  	ptr := unsafe.Pointer(C.malloc(size))
    82  	copy(unsafe.Slice((*byte)(ptr), size), s)
    83  	return uint32(uintptr(ptr)), uint32(size)
    84  }