7
7
from typing import Callable , Optional , Generic , TypeVar , List , Union , Tuple , cast as cast_type , Sequence
8
8
from ._exportable import AsExtern
9
9
from ._store import Storelike
10
- from ._bindings import wasmtime_val_raw_t , wasm_valtype_kind
10
+ from ._bindings import wasmtime_val_raw_t , wasm_valtype_kind , wasmtime_val_t , wasmtime_externref_t , wasmtime_func_t
11
+ from ._value import _unintern
11
12
from ._ffi import (
12
13
WASMTIME_I32 ,
13
14
WASMTIME_I64 ,
18
19
WASMTIME_EXTERNREF ,
19
20
WASM_ANYREF ,
20
21
WASM_FUNCREF ,
22
+ wasmtime_externref_data ,
21
23
)
22
24
23
25
40
42
def get_valtype_attr (ty : ValType ):
41
43
return val_id2attr [wasm_valtype_kind (ty ._ptr )]
42
44
45
+ from struct import Struct
46
+
47
+ def val_getter (store_id , val_raw , attr ):
48
+ val = getattr (val_raw , attr )
49
+
50
+ if attr == 'externref' :
51
+ ptr = ctypes .POINTER (wasmtime_externref_t )
52
+ if not val : return None
53
+ ffi = ptr .from_address (val )
54
+ if not ffi : return
55
+ extern_id = wasmtime_externref_data (ffi )
56
+ ret = _unintern (extern_id )
57
+ return ret
58
+ elif attr == 'funcref' :
59
+ if val == 0 : return None
60
+ f = wasmtime_func_t ()
61
+ f .store_id = store_id
62
+ f .index = val
63
+ ret = Func ._from_raw (f )
64
+ return ret
65
+ return val
66
+
43
67
def val_setter (dst , attr , val ):
44
68
if attr == 'externref' :
45
- # TODO: handle None
46
- v = Val .externref (val )
47
- casted = ctypes .addressof (v ._raw .of .externref )
69
+ if isinstance (val , Val ) and val ._raw .kind == WASMTIME_EXTERNREF .value :
70
+ if val ._raw .of .externref :
71
+ extern_id = wasmtime_externref_data (val ._raw .of .externref )
72
+ casted = ctypes .addressof (val ._raw .of .externref )
73
+ else :
74
+ v = Val .externref (val )
75
+ casted = ctypes .addressof (v ._raw .of .externref )
76
+ elif attr == 'funcref' :
77
+ if isinstance (val , Val ) and val ._raw .kind == WASMTIME_FUNCREF .value :
78
+ casted = val ._raw .of .funcref .index
79
+ else : raise RuntimeError ("foo" )
48
80
elif isinstance (val , Func ):
49
81
# TODO: handle null_funcref
50
82
# TODO: validate same val._func.store_id
@@ -112,9 +144,10 @@ def _extract_return(self, vals_raw: ctypes.Array[wasmtime_val_raw_t]) -> Union[I
112
144
if self ._results_n == 0 :
113
145
return None
114
146
if self ._results_n == 1 :
115
- return getattr (vals_raw [0 ], self ._results_str0 )
147
+ ret = val_getter (self ._func .store_id , vals_raw [0 ], self ._results_str0 )
148
+ return ret
116
149
# we can use tuple construct, but I'm using list for compatability
117
- return [getattr ( val_raw , ret_str ) for val_raw , ret_str in zip (vals_raw , self ._results_str )]
150
+ return [val_getter ( self . _func . store_id , val_raw , ret_str ) for val_raw , ret_str in zip (vals_raw , self ._results_str )]
118
151
119
152
def _init_call (self , ty : FuncType ):
120
153
"""init signature properties used by call"""
@@ -123,8 +156,8 @@ def _init_call(self, ty: FuncType):
123
156
ty_results = ty .results
124
157
params_n = len (ty_params )
125
158
results_n = len (ty_results )
126
- self ._params_str = ( get_valtype_attr (i ) for i in ty_params )
127
- self ._results_str = ( get_valtype_attr (i ) for i in ty_results )
159
+ self ._params_str = [ get_valtype_attr (i ) for i in ty_params ]
160
+ self ._results_str = [ get_valtype_attr (i ) for i in ty_results ]
128
161
self ._results_str0 = get_valtype_attr (ty_results [0 ]) if results_n else None
129
162
self ._params_n = params_n
130
163
self ._results_n = results_n
0 commit comments