-
Notifications
You must be signed in to change notification settings - Fork 79
/
instance.go
119 lines (111 loc) · 3 KB
/
instance.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package wasmtime
// #include "shims.h"
import "C"
import (
"runtime"
"unsafe"
)
// Instance is an instantiated module instance.
// Once a module has been instantiated as an Instance, any exported function can be invoked externally via its function address funcaddr in the store S and an appropriate list val∗ of argument values.
type Instance struct {
val C.wasmtime_instance_t
}
// NewInstance instantiates a WebAssembly `module` with the `imports` provided.
//
// This function will attempt to create a new wasm instance given the provided
// imports. This can fail if the wrong number of imports are specified, the
// imports aren't of the right type, or for other resource-related issues.
//
// This will also run the `start` function of the instance, returning an error
// if it traps.
func NewInstance(store Storelike, module *Module, imports []AsExtern) (*Instance, error) {
importsRaw := make([]C.wasmtime_extern_t, len(imports))
for i, imp := range imports {
importsRaw[i] = imp.AsExtern()
}
var val C.wasmtime_instance_t
err := enterWasm(store, func(trap **C.wasm_trap_t) *C.wasmtime_error_t {
var imports *C.wasmtime_extern_t
if len(importsRaw) > 0 {
imports = (*C.wasmtime_extern_t)(unsafe.Pointer(&importsRaw[0]))
}
return C.wasmtime_instance_new(
store.Context(),
module.ptr(),
imports,
C.size_t(len(importsRaw)),
&val,
trap,
)
})
runtime.KeepAlive(store)
runtime.KeepAlive(module)
runtime.KeepAlive(imports)
runtime.KeepAlive(importsRaw)
if err != nil {
return nil, err
}
return mkInstance(val), nil
}
func mkInstance(val C.wasmtime_instance_t) *Instance {
return &Instance{val}
}
type externList struct {
vec C.wasm_extern_vec_t
}
// Exports returns a list of exports from this instance.
//
// Each export is returned as a `*Extern` and lines up with the exports list of
// the associated `Module`.
func (instance *Instance) Exports(store Storelike) []*Extern {
ret := make([]*Extern, 0)
var name *C.char
var name_len C.size_t
for i := 0; ; i++ {
var item C.wasmtime_extern_t
ok := C.wasmtime_instance_export_nth(
store.Context(),
&instance.val,
C.size_t(i),
&name,
&name_len,
&item,
)
if !ok {
break
}
ret = append(ret, mkExtern(&item))
}
runtime.KeepAlive(store)
return ret
}
// GetExport attempts to find an export on this instance by `name`
//
// May return `nil` if this instance has no export named `name`
func (i *Instance) GetExport(store Storelike, name string) *Extern {
var item C.wasmtime_extern_t
ok := C.wasmtime_instance_export_get(
store.Context(),
&i.val,
C._GoStringPtr(name),
C._GoStringLen(name),
&item,
)
runtime.KeepAlive(store)
runtime.KeepAlive(name)
if ok {
return mkExtern(&item)
}
return nil
}
// GetFunc attempts to find a function on this instance by `name`.
//
// May return `nil` if this instance has no function named `name`,
// it is not a function, etc.
func (i *Instance) GetFunc(store Storelike, name string) *Func {
f := i.GetExport(store, name)
if f == nil {
return nil
}
return f.Func()
}