Skip to content

Commit

Permalink
Delay actually loading the runtime to fix property setting
Browse files Browse the repository at this point in the history
  • Loading branch information
filmor committed Aug 7, 2023
1 parent 63d7f69 commit 600b5fa
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 12 deletions.
20 changes: 9 additions & 11 deletions clr_loader/hostfxr.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ def __init__(self, runtime_config: Path, dotnet_root: Path, **params: str):

self._dotnet_root = Path(dotnet_root)
self._dll = load_hostfxr(self._dotnet_root)
self._is_initialized = False
self._handle = _get_handle(self._dll, self._dotnet_root, runtime_config)
self._load_func = _get_load_func(self._dll, self._handle)
self._load_func = None

for key, value in params.items():
self[key] = value
Expand All @@ -36,7 +35,7 @@ def dotnet_root(self) -> Path:

@property
def is_initialized(self) -> bool:
return self._is_initialized
return self._load_func is not None

@property
def is_shutdown(self) -> bool:
Expand Down Expand Up @@ -81,18 +80,23 @@ def __iter__(self) -> Generator[Tuple[str, str], None, None]:
for i in range(size_ptr[0]):
yield (decode(keys_ptr[i]), decode(values_ptr[i]))

def _get_load_func(self):
if self._load_func is None:
self._load_func = _get_load_func(self._dll, self._handle)

return self._load_func

def _get_callable(self, assembly_path: StrOrPath, typename: str, function: str):
# TODO: Maybe use coreclr_get_delegate as well, supported with newer API
# versions of hostfxr
self._is_initialized = True

# Append assembly name to typename
assembly_path = Path(assembly_path)
assembly_name = assembly_path.stem
typename = f"{typename}, {assembly_name}"

delegate_ptr = ffi.new("void**")
res = self._load_func(
res = self._get_load_func()(
encode(str(assembly_path)),
encode(typename),
encode(function),
Expand All @@ -103,12 +107,6 @@ def _get_callable(self, assembly_path: StrOrPath, typename: str, function: str):
check_result(res)
return ffi.cast("component_entry_point_fn", delegate_ptr[0])

def _check_initialized(self) -> None:
if self._handle is None:
raise RuntimeError("Runtime is shut down")
elif not self._is_initialized:
raise RuntimeError("Runtime is not initialized")

def shutdown(self) -> None:
if self._handle is not None:
self._dll.hostfxr_close(self._handle)
Expand Down
14 changes: 13 additions & 1 deletion tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def example_netcore(tmpdir_factory):

def build_example(tmpdir_factory, framework):
out = Path(tmpdir_factory.mktemp(f"example-{framework}"))
proj_path = Path(__file__).parent.parent / "example"
proj_path = Path(__file__).parent.parent / "example" / "example.csproj"

check_call(["dotnet", "build", str(proj_path), "-o", str(out), "-f", framework])

Expand Down Expand Up @@ -75,6 +75,18 @@ def test_coreclr(example_netcore: Path):
run_tests(asm)


def test_coreclr_properties(example_netcore: Path):
from clr_loader import get_coreclr

coreclr = get_coreclr(
runtime_config=example_netcore / "example.runtimeconfig.json",
properties=dict(APP_CONTEXT_BASE_DIRECTORY=str(example_netcore)),
)
asm = coreclr.get_assembly(example_netcore / "example.dll")

run_tests(asm)


def test_coreclr_autogenerated_runtimeconfig(example_netstandard: Path):
from multiprocessing import get_context

Expand Down

0 comments on commit 600b5fa

Please sign in to comment.