Coverage for wasmtime/_instance.py: 97%

62 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-02-20 16:25 +0000

1from . import _ffi as ffi 

2from ctypes import POINTER, byref 

3from wasmtime import Module, WasmtimeError 

4from ._extern import wrap_extern, get_extern_ptr 

5from ._exportable import AsExtern 

6from typing import Sequence, Optional, Iterator, Mapping 

7from ._store import Storelike 

8from ._func import enter_wasm 

9 

10 

11class Instance: 

12 _instance: ffi.wasmtime_instance_t 

13 _exports: Optional["InstanceExports"] 

14 

15 def __init__(self, store: Storelike, module: Module, imports: Sequence[AsExtern]): 

16 """ 

17 Creates a new instance by instantiating the `module` given with the 

18 `imports` into the `store` provided. 

19 

20 The `store` must have type `Store`, the `module` must have type 

21 `Module`, and the `imports` must be an iterable of external values, 

22 either `Extern`, `Func`, `Table`, `Memory`, or `Global`. 

23 

24 Raises an error if instantiation fails (e.g. linking or trap) and 

25 otherwise initializes the new instance. 

26 """ 

27 

28 imports_ptr = (ffi.wasmtime_extern_t * len(imports))() 

29 for i, val in enumerate(imports): 

30 imports_ptr[i] = get_extern_ptr(val) 

31 

32 instance = ffi.wasmtime_instance_t() 

33 with enter_wasm(store) as trap: 

34 error = ffi.wasmtime_instance_new( 

35 store._context(), 

36 module.ptr(), 

37 imports_ptr, 

38 len(imports), 

39 byref(instance), 

40 trap) 

41 if error: 

42 raise WasmtimeError._from_ptr(error) 

43 self._instance = instance 

44 self._exports = None 

45 

46 @classmethod 

47 def _from_raw(cls, instance: ffi.wasmtime_instance_t) -> "Instance": 

48 ty: "Instance" = cls.__new__(cls) 

49 ty._exports = None 

50 ty._instance = instance 

51 return ty 

52 

53 def exports(self, store: Storelike) -> "InstanceExports": 

54 """ 

55 Returns the exports of this module 

56 

57 The returned type can be indexed both with integers and with strings for 

58 names of exports. 

59 """ 

60 if self._exports is None: 

61 self._exports = InstanceExports(store, self) 

62 return self._exports 

63 

64 def _as_extern(self) -> ffi.wasmtime_extern_t: 

65 union = ffi.wasmtime_extern_union(instance=self._instance) 

66 return ffi.wasmtime_extern_t(ffi.WASMTIME_EXTERN_INSTANCE, union) 

67 

68 

69class InstanceExports(Mapping[str, AsExtern]): 

70 _extern_seq: Sequence[AsExtern] 

71 _extern_map: Mapping[str, AsExtern] 

72 

73 def __init__(self, store: Storelike, instance: Instance): 

74 self._extern_map = {} 

75 

76 extern_list = [] 

77 i = 0 

78 item = ffi.wasmtime_extern_t() 

79 name_ptr = POINTER(ffi.c_char)() 

80 name_len = ffi.c_size_t(0) 

81 while ffi.wasmtime_instance_export_nth( 

82 store._context(), 

83 byref(instance._instance), 

84 i, 

85 byref(name_ptr), 

86 byref(name_len), 

87 byref(item)): 

88 name = ffi.to_str_raw(name_ptr, name_len.value) 

89 extern = wrap_extern(item) 

90 extern_list.append(extern) 

91 self._extern_map[name] = extern 

92 i += 1 

93 item = ffi.wasmtime_extern_t() 

94 self._extern_seq = tuple(extern_list) 

95 

96 @property 

97 def by_index(self) -> Sequence[AsExtern]: 

98 return self._extern_seq 

99 

100 def __getitem__(self, idx: str) -> AsExtern: 

101 return self._extern_map[idx] 

102 

103 def __len__(self) -> int: 

104 return len(self.by_index) 

105 

106 def __iter__(self) -> Iterator[str]: 

107 return iter(self._extern_map)