1
1
import os
2
- import shutil
3
2
import sys
3
+ from typing import Optional
4
4
5
5
from .ffi import ffi , load_hostfxr
6
- from .util import check_result
6
+ from .util import check_result , find_dotnet_root
7
7
8
- __all__ = ["HostFxr " ]
8
+ __all__ = ["DotnetCoreRuntime " ]
9
9
10
10
11
- class HostFxr :
12
- # TODO: Allow generating runtime_config
13
- def __init__ (self , runtime_config , dotnet_root = None ):
14
- self ._handle = None
11
+ class DotnetCoreRuntime :
12
+ def __init__ (self , runtime_config : str , dotnet_root : Optional [str ] = None ):
13
+ self ._dotnet_root = dotnet_root or find_dotnet_root ()
14
+ self ._dll = load_hostfxr (self ._dotnet_root )
15
+ self ._is_finalized = False
16
+ self ._handle = _get_handle (self ._dll , self ._dotnet_root , runtime_config )
17
+ self ._load_func = _get_load_func (self ._dll , self ._handle )
15
18
16
- if not dotnet_root :
17
- dotnet_root = os .environ .get ("DOTNET_ROOT" , None )
19
+ @property
20
+ def dotnet_root (self ):
21
+ return self ._dotnet_root
18
22
19
- if not dotnet_root and sys .platform == "win32" :
20
- # On Windows, the host library is stored separately from dotnet.exe for x86
21
- if sys .maxsize > 2 ** 32 :
22
- possible_root = os .path .join (os .environ .get ("ProgramFiles" ), "dotnet" )
23
- else :
24
- possible_root = os .path .join (
25
- os .environ .get ("ProgramFiles(x86)" ), "dotnet"
26
- )
23
+ @property
24
+ def is_finalized (self ):
25
+ return self ._is_finalized
27
26
28
- if os .path .isdir (possible_root ):
29
- dotnet_root = possible_root
27
+ def __getitem__ (self , key : str ) -> str :
28
+ buf = ffi .new ("char_t**" )
29
+ res = self ._dll .hostfxr_get_runtime_property_value (
30
+ self ._handle , encode (key ), buf
31
+ )
32
+ if res != 0 :
33
+ raise KeyError (key )
30
34
31
- if not dotnet_root :
32
- dotnet_path = shutil .which ("dotnet" )
33
- if not dotnet_path :
34
- raise RuntimeError ("Can not determine dotnet root" )
35
+ return decode (buf [0 ])
35
36
36
- try :
37
- # Pypy does not provide os.readlink right now
38
- if hasattr (os , "readlink" ):
39
- dotnet_tmp_path = os .readlink (dotnet_path )
40
- else :
41
- dotnet_tmp_path = dotnet_path
37
+ def __setitem__ (self , key : str , value : str ) -> None :
38
+ if self .is_finalized :
39
+ raise RuntimeError ("Already finalized" )
42
40
43
- if os .path .isabs (dotnet_tmp_path ):
44
- dotnet_path = dotnet_tmp_path
45
- else :
46
- dotnet_path = os .path .abspath (
47
- os .path .join (os .path .dirname (dotnet_path ), dotnet_tmp_path )
48
- )
49
- except OSError :
50
- pass
41
+ res = self ._dll .hostfxr_set_runtime_property_value (
42
+ self ._handle , encode (key ), encode (value )
43
+ )
44
+ check_result (res )
51
45
52
- dotnet_root = os .path .dirname (dotnet_path )
46
+ def __iter__ (self ):
47
+ max_size = 100
48
+ size_ptr = ffi .new ("size_t*" )
49
+ size_ptr [0 ] = max_size
53
50
54
- self . _dll = load_hostfxr ( dotnet_root )
55
- self . _dotnet_root = dotnet_root
51
+ keys_ptr = ffi . new ( "char_t*[]" , max_size )
52
+ values_ptr = ffi . new ( "char_t*[]" , max_size )
56
53
57
- self ._handle = _get_handle (self ._dll , self ._dotnet_root , runtime_config )
58
- self ._load_func = _get_load_func (self ._dll , self ._handle )
54
+ res = self ._fxr ._dll .hostfxr_get_runtime_properties (
55
+ self ._fxr ._handle , size_ptr , keys_ptr , values_ptr
56
+ )
57
+ check_result (res )
58
+
59
+ for i in range (size_ptr [0 ]):
60
+ yield (decode (keys_ptr [i ]), decode (values_ptr [i ]))
59
61
60
62
def get_callable (self , assembly_path , typename , function ):
63
+ # TODO: Maybe use coreclr_get_delegate as well, supported with newer API
64
+ # versions of hostfxr
65
+ self ._is_finalized = True
66
+
61
67
# Append assembly name to typename
62
68
assembly_name , _ = os .path .splitext (os .path .basename (assembly_path ))
63
69
typename = f"{ typename } , { assembly_name } "
@@ -82,47 +88,6 @@ def shutdown(self):
82
88
def __del__ (self ):
83
89
self .shutdown ()
84
90
85
- @property
86
- def props (self ):
87
- return HostFxrProps (self )
88
-
89
-
90
- class HostFxrProps :
91
- def __init__ (self , fxr ):
92
- self ._fxr = fxr
93
-
94
- def __getitem__ (self , key ):
95
- buf = ffi .new ("char_t**" )
96
- res = self ._fxr ._dll .hostfxr_get_runtime_property_value (
97
- self ._fxr ._handle , encode (key ), buf
98
- )
99
- if res != 0 :
100
- raise KeyError (key )
101
-
102
- return decode (buf [0 ])
103
-
104
- def __setitem__ (self , key , value ):
105
- res = self ._fxr ._dll .hostfxr_set_runtime_property_value (
106
- self ._fxr ._handle , encode (key ), encode (value )
107
- )
108
- check_result (res )
109
-
110
- def __iter__ (self ):
111
- max_size = 100
112
- size_ptr = ffi .new ("size_t*" )
113
- size_ptr [0 ] = max_size
114
-
115
- keys_ptr = ffi .new ("char_t*[]" , max_size )
116
- values_ptr = ffi .new ("char_t*[]" , max_size )
117
-
118
- res = self ._fxr ._dll .hostfxr_get_runtime_properties (
119
- self ._fxr ._handle , size_ptr , keys_ptr , values_ptr
120
- )
121
- check_result (res )
122
-
123
- for i in range (size_ptr [0 ]):
124
- yield (decode (keys_ptr [i ]), decode (values_ptr [i ]))
125
-
126
91
127
92
def _get_handle (dll , dotnet_root , runtime_config ):
128
93
params = ffi .new ("hostfxr_initialize_parameters*" )
0 commit comments