77from typing import Callable , Optional , Generic , TypeVar , List , Union , Tuple , cast as cast_type , Sequence
88from ._exportable import AsExtern
99from ._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
1112from ._ffi import (
1213 WASMTIME_I32 ,
1314 WASMTIME_I64 ,
1819 WASMTIME_EXTERNREF ,
1920 WASM_ANYREF ,
2021 WASM_FUNCREF ,
22+ wasmtime_externref_data ,
2123)
2224
2325
4042def get_valtype_attr (ty : ValType ):
4143 return val_id2attr [wasm_valtype_kind (ty ._ptr )]
4244
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+
4367def val_setter (dst , attr , val ):
4468 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" )
4880 elif isinstance (val , Func ):
4981 # TODO: handle null_funcref
5082 # 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
112144 if self ._results_n == 0 :
113145 return None
114146 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
116149 # 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 )]
118151
119152 def _init_call (self , ty : FuncType ):
120153 """init signature properties used by call"""
@@ -123,8 +156,8 @@ def _init_call(self, ty: FuncType):
123156 ty_results = ty .results
124157 params_n = len (ty_params )
125158 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 ]
128161 self ._results_str0 = get_valtype_attr (ty_results [0 ]) if results_n else None
129162 self ._params_n = params_n
130163 self ._results_n = results_n
0 commit comments