Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add get_coreclr_command_line which uses hostfxr_initialize_for_dotnet_command_line #66

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions clr_loader/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"get_mono",
"get_netfx",
"get_coreclr",
"get_coreclr_command_line",
"find_dotnet_root",
"find_libmono",
"find_runtimes",
Expand Down Expand Up @@ -150,6 +151,39 @@ def get_coreclr(
return impl


def get_coreclr_command_line(
*,
entry_dll: StrOrPath,
dotnet_root: Optional[StrOrPath] = None,
properties: Optional[Dict[str, str]] = None
) -> Runtime:
"""Get a CoreCLR (.NET Core) runtime instance
The returned ``DotnetCoreRuntimeCommandLine`` also acts as a mapping of the config
properties. They can be retrieved using the index operator and can be
written until the runtime is initialized. The runtime is initialized when
the first function object is retrieved.
:param entry_dll:
The path to the entry dll.
:param dotnet_root:
The root directory of the .NET Core installation. If this is not
specified, we try to discover it using :py:func:`find_dotnet_root`.
:param properties:
Additional runtime properties. These can also be passed using the
``configProperties`` section in the runtime config."""
from .hostfxr import DotnetCoreCommandRuntime

dotnet_root = _maybe_path(dotnet_root)
if dotnet_root is None:
dotnet_root = find_dotnet_root()

impl = DotnetCoreCommandRuntime(entry_dll=_maybe_path(entry_dll), dotnet_root=dotnet_root)
if properties:
for key, value in properties.items():
impl[key] = value

return impl


def get_netfx(
*, domain: Optional[str] = None, config_file: Optional[StrOrPath] = None
) -> Runtime:
Expand Down
64 changes: 53 additions & 11 deletions clr_loader/hostfxr.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,24 @@
from .types import Runtime, RuntimeInfo, StrOrPath
from .util import check_result

__all__ = ["DotnetCoreRuntime"]
__all__ = ["DotnetCoreRuntime", "DotnetCoreCommandRuntime"]

_IS_SHUTDOWN = False


class DotnetCoreRuntime(Runtime):
def __init__(self, runtime_config: Path, dotnet_root: Path, **params: str):
class DotnetCoreRuntimeBase(Runtime):
_version: str

def __init__(self, dotnet_root: Path):
self._handle = None

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

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

for key, value in params.items():
self[key] = value

# TODO: Get version
self._version = "<undefined>"

@property
def dotnet_root(self) -> Path:
return self._dotnet_root
Expand Down Expand Up @@ -122,7 +117,31 @@ def info(self):
)


def _get_handle(dll, dotnet_root: StrOrPath, runtime_config: StrOrPath):
class DotnetCoreRuntime(DotnetCoreRuntimeBase):
def __init__(self, runtime_config: Path, dotnet_root: Path, **params: str):
super().__init__(dotnet_root)
self._handle = _get_handle_for_runtime_config(self._dll, self._dotnet_root, runtime_config)

for key, value in params.items():
self[key] = value

# TODO: Get version
self._version = "<undefined>"


class DotnetCoreCommandRuntime(DotnetCoreRuntimeBase):
def __init__(self, entry_dll: Path, dotnet_root: Path, **params: str):
super().__init__(dotnet_root)
self._handle = _get_handle_for_dotnet_command_line(self._dll, self._dotnet_root, entry_dll)

for key, value in params.items():
self[key] = value

# TODO: Get version
self._version = "<undefined>"


def _get_handle_for_runtime_config(dll, dotnet_root: StrOrPath, runtime_config: StrOrPath):
params = ffi.new("hostfxr_initialize_parameters*")
params.size = ffi.sizeof("hostfxr_initialize_parameters")
# params.host_path = ffi.new("char_t[]", encode(sys.executable))
Expand All @@ -140,6 +159,29 @@ def _get_handle(dll, dotnet_root: StrOrPath, runtime_config: StrOrPath):
return handle_ptr[0]


def _get_handle_for_dotnet_command_line(dll, dotnet_root: StrOrPath, entry_dll: StrOrPath):
params = ffi.new("hostfxr_initialize_parameters*")
params.size = ffi.sizeof("hostfxr_initialize_parameters")
params.host_path = ffi.NULL
dotnet_root_p = ffi.new("char_t[]", encode(str(Path(dotnet_root))))
params.dotnet_root = dotnet_root_p

handle_ptr = ffi.new("hostfxr_handle*")

args_ptr = ffi.new("char_t*[1]")
arg_ptr = ffi.new("char_t[]", encode(str(Path(entry_dll))))
args_ptr[0] = arg_ptr
res = dll.hostfxr_initialize_for_dotnet_command_line(
1,
args_ptr,
params, handle_ptr
)

check_result(res)

return handle_ptr[0]


def _get_load_func(dll, handle):
delegate_ptr = ffi.new("void**")

Expand Down
13 changes: 13 additions & 0 deletions tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ def test_coreclr(example_netcore: Path):
run_tests(asm)


def test_coreclr_command_line(example_netcore: Path):
run_in_subprocess(_do_test_coreclr_command_line, example_netcore)


def _do_test_coreclr_command_line(example_netcore):
from clr_loader import get_coreclr_command_line

coreclr = get_coreclr_command_line(entry_dll=example_netcore / "example.dll")
asm = coreclr.get_assembly(example_netcore / "example.dll")

run_tests(asm)


def test_coreclr_properties(example_netcore: Path):
run_in_subprocess(
_do_test_coreclr_autogenerated_runtimeconfig,
Expand Down
Loading