Coverage for wasmtime/_instance.py: 100%

56 statements  

« prev     ^ index     » next       coverage.py v7.11.3, created at 2025-12-01 19:40 +0000

1import ctypes 

2 

3from . import _ffi as ffi 

4from ctypes import POINTER, byref 

5from wasmtime import Module, WasmtimeError 

6from ._extern import wrap_extern, get_extern_ptr 

7from ._exportable import AsExtern 

8from typing import Sequence, Optional, Iterator, Mapping 

9from ._store import Storelike 

10from ._func import enter_wasm 

11 

12 

13class Instance: 

14 _instance: ffi.wasmtime_instance_t 

15 _exports: Optional["InstanceExports"] 

16 

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

18 """ 

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

20 `imports` into the `store` provided. 

21 

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

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

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

25 

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

27 otherwise initializes the new instance. 

28 """ 

29 

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

31 for i, val in enumerate(imports): 

32 imports_ptr[i] = get_extern_ptr(val) 

33 

34 instance = ffi.wasmtime_instance_t() 

35 with enter_wasm(store) as trap: 

36 error = ffi.wasmtime_instance_new( 

37 store._context(), 

38 module.ptr(), 

39 imports_ptr, 

40 len(imports), 

41 byref(instance), 

42 trap) 

43 if error: 

44 raise WasmtimeError._from_ptr(error) 

45 self._instance = instance 

46 self._exports = None 

47 

48 @classmethod 

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

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

51 ty._exports = None 

52 ty._instance = instance 

53 return ty 

54 

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

56 """ 

57 Returns the exports of this module 

58 

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

60 names of exports. 

61 """ 

62 if self._exports is None: 

63 self._exports = InstanceExports(store, self) 

64 return self._exports 

65 

66 

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

68 _extern_seq: Sequence[AsExtern] 

69 _extern_map: Mapping[str, AsExtern] 

70 

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

72 self._extern_map = {} 

73 

74 extern_list = [] 

75 i = 0 

76 item = ffi.wasmtime_extern_t() 

77 name_ptr = ctypes.POINTER(ctypes.c_char)() 

78 name_len = ctypes.c_size_t(0) 

79 while ffi.wasmtime_instance_export_nth( 

80 store._context(), 

81 byref(instance._instance), 

82 i, 

83 byref(name_ptr), 

84 byref(name_len), 

85 byref(item)): 

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

87 extern = wrap_extern(item) 

88 extern_list.append(extern) 

89 self._extern_map[name] = extern 

90 i += 1 

91 item = ffi.wasmtime_extern_t() 

92 self._extern_seq = tuple(extern_list) 

93 

94 @property 

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

96 return self._extern_seq 

97 

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

99 return self._extern_map[idx] 

100 

101 def __len__(self) -> int: 

102 return len(self.by_index) 

103 

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

105 return iter(self._extern_map)