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