Skip to content

Commit 8c123c6

Browse files
Add get_coreclr_command_line which uses hostfxr_initialize_for_dotnet_command_line (#66)
see https://github.com/dotnet/runtime/blob/main/docs/design/features/native-hosting.md#initializing-host-context
1 parent eeed6ec commit 8c123c6

File tree

3 files changed

+100
-11
lines changed

3 files changed

+100
-11
lines changed

clr_loader/__init__.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"get_mono",
1212
"get_netfx",
1313
"get_coreclr",
14+
"get_coreclr_command_line",
1415
"find_dotnet_root",
1516
"find_libmono",
1617
"find_runtimes",
@@ -152,6 +153,39 @@ def get_coreclr(
152153
return impl
153154

154155

156+
def get_coreclr_command_line(
157+
*,
158+
entry_dll: StrOrPath,
159+
dotnet_root: Optional[StrOrPath] = None,
160+
properties: Optional[Dict[str, str]] = None
161+
) -> Runtime:
162+
"""Get a CoreCLR (.NET Core) runtime instance
163+
The returned ``DotnetCoreRuntimeCommandLine`` also acts as a mapping of the config
164+
properties. They can be retrieved using the index operator and can be
165+
written until the runtime is initialized. The runtime is initialized when
166+
the first function object is retrieved.
167+
:param entry_dll:
168+
The path to the entry dll.
169+
:param dotnet_root:
170+
The root directory of the .NET Core installation. If this is not
171+
specified, we try to discover it using :py:func:`find_dotnet_root`.
172+
:param properties:
173+
Additional runtime properties. These can also be passed using the
174+
``configProperties`` section in the runtime config."""
175+
from .hostfxr import DotnetCoreCommandRuntime
176+
177+
dotnet_root = _maybe_path(dotnet_root)
178+
if dotnet_root is None:
179+
dotnet_root = find_dotnet_root()
180+
181+
impl = DotnetCoreCommandRuntime(entry_dll=_maybe_path(entry_dll), dotnet_root=dotnet_root)
182+
if properties:
183+
for key, value in properties.items():
184+
impl[key] = value
185+
186+
return impl
187+
188+
155189
def get_netfx(
156190
*, domain: Optional[str] = None, config_file: Optional[StrOrPath] = None
157191
) -> Runtime:

clr_loader/hostfxr.py

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,24 @@
66
from .types import Runtime, RuntimeInfo, StrOrPath
77
from .util import check_result
88

9-
__all__ = ["DotnetCoreRuntime"]
9+
__all__ = ["DotnetCoreRuntime", "DotnetCoreCommandRuntime"]
1010

1111
_IS_SHUTDOWN = False
1212

1313

14-
class DotnetCoreRuntime(Runtime):
15-
def __init__(self, runtime_config: Path, dotnet_root: Path, **params: str):
14+
class DotnetCoreRuntimeBase(Runtime):
15+
_version: str
16+
17+
def __init__(self, dotnet_root: Path):
1618
self._handle = None
1719

1820
if _IS_SHUTDOWN:
1921
raise RuntimeError("Runtime can not be reinitialized")
2022

2123
self._dotnet_root = Path(dotnet_root)
2224
self._dll = load_hostfxr(self._dotnet_root)
23-
self._handle = _get_handle(self._dll, self._dotnet_root, runtime_config)
2425
self._load_func = None
2526

26-
for key, value in params.items():
27-
self[key] = value
28-
29-
# TODO: Get version
30-
self._version = "<undefined>"
31-
3227
@property
3328
def dotnet_root(self) -> Path:
3429
return self._dotnet_root
@@ -122,7 +117,31 @@ def info(self):
122117
)
123118

124119

125-
def _get_handle(dll, dotnet_root: StrOrPath, runtime_config: StrOrPath):
120+
class DotnetCoreRuntime(DotnetCoreRuntimeBase):
121+
def __init__(self, runtime_config: Path, dotnet_root: Path, **params: str):
122+
super().__init__(dotnet_root)
123+
self._handle = _get_handle_for_runtime_config(self._dll, self._dotnet_root, runtime_config)
124+
125+
for key, value in params.items():
126+
self[key] = value
127+
128+
# TODO: Get version
129+
self._version = "<undefined>"
130+
131+
132+
class DotnetCoreCommandRuntime(DotnetCoreRuntimeBase):
133+
def __init__(self, entry_dll: Path, dotnet_root: Path, **params: str):
134+
super().__init__(dotnet_root)
135+
self._handle = _get_handle_for_dotnet_command_line(self._dll, self._dotnet_root, entry_dll)
136+
137+
for key, value in params.items():
138+
self[key] = value
139+
140+
# TODO: Get version
141+
self._version = "<undefined>"
142+
143+
144+
def _get_handle_for_runtime_config(dll, dotnet_root: StrOrPath, runtime_config: StrOrPath):
126145
params = ffi.new("hostfxr_initialize_parameters*")
127146
params.size = ffi.sizeof("hostfxr_initialize_parameters")
128147
# params.host_path = ffi.new("char_t[]", encode(sys.executable))
@@ -140,6 +159,29 @@ def _get_handle(dll, dotnet_root: StrOrPath, runtime_config: StrOrPath):
140159
return handle_ptr[0]
141160

142161

162+
def _get_handle_for_dotnet_command_line(dll, dotnet_root: StrOrPath, entry_dll: StrOrPath):
163+
params = ffi.new("hostfxr_initialize_parameters*")
164+
params.size = ffi.sizeof("hostfxr_initialize_parameters")
165+
params.host_path = ffi.NULL
166+
dotnet_root_p = ffi.new("char_t[]", encode(str(Path(dotnet_root))))
167+
params.dotnet_root = dotnet_root_p
168+
169+
handle_ptr = ffi.new("hostfxr_handle*")
170+
171+
args_ptr = ffi.new("char_t*[1]")
172+
arg_ptr = ffi.new("char_t[]", encode(str(Path(entry_dll))))
173+
args_ptr[0] = arg_ptr
174+
res = dll.hostfxr_initialize_for_dotnet_command_line(
175+
1,
176+
args_ptr,
177+
params, handle_ptr
178+
)
179+
180+
check_result(res)
181+
182+
return handle_ptr[0]
183+
184+
143185
def _get_load_func(dll, handle):
144186
delegate_ptr = ffi.new("void**")
145187

tests/test_common.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,19 @@ def test_coreclr(example_netcore: Path):
9292
run_tests(asm)
9393

9494

95+
def test_coreclr_command_line(example_netcore: Path):
96+
run_in_subprocess(_do_test_coreclr_command_line, example_netcore)
97+
98+
99+
def _do_test_coreclr_command_line(example_netcore):
100+
from clr_loader import get_coreclr_command_line
101+
102+
coreclr = get_coreclr_command_line(entry_dll=example_netcore / "example.dll")
103+
asm = coreclr.get_assembly(example_netcore / "example.dll")
104+
105+
run_tests(asm)
106+
107+
95108
def test_coreclr_properties(example_netcore: Path):
96109
run_in_subprocess(
97110
_do_test_coreclr_autogenerated_runtimeconfig,

0 commit comments

Comments
 (0)