Skip to content

Implement WinRT / C# projection for the WSLC SDK API surface#40360

Draft
florelis wants to merge 12 commits into
microsoft:masterfrom
florelis:csFullApi
Draft

Implement WinRT / C# projection for the WSLC SDK API surface#40360
florelis wants to merge 12 commits into
microsoft:masterfrom
florelis:csFullApi

Conversation

@florelis
Copy link
Copy Markdown
Member

@florelis florelis commented Apr 29, 2026

Summary of the Pull Request

This PR the C++/WinRT wrapper for the WSLC SDK, which is then projected to C#.

PR Checklist

  • Closes: Link to issue #xxx
  • Communication: I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
  • Tests: Added/updated if needed and all pass
  • Localization: All end user facing strings can be localized
  • Dev docs: Added/updated if needed
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

This builds on top of #40121 and #40212. The relevant changes for this are only the .h and .cpp files.

The implementation for all types follows a similar pattern, but there are some differences between types that are meant to be constructed by the consumer (e.g., SessionSettings) and types that can only be obtained by a function call (e.g., Session).

For types constructed by the consumer:

  • Added constructors to the implementation types that don't have one in the public API
  • Declared private fields to back all the properties
  • All getters and setters use the backing fields directly
  • Setters perform minimal validation (e.g., non-empty strings)
  • String values are not stored as a WinRT hstring but as a native std::(w)string to directly back any string pointers passed to the C API.
  • Properties that in the C API use 0 to represent the default value, here use instead an IReference<> (projected to C# as a nullable type) and nullptr to represent the default.
  • Added a ToStruct() or ToStructPointer() (depending on usage) to get and retrieve the equivalent struct for the C API. This native struct is cached so that we only create it once. To avoid dealing with updating the native object if a property is changed, I blocked all setters if the native struct was already created.

For the types that are only constructed by the API:

  • Added a backing field for pointer to the handle returned by the API
  • Most functions are just forwarding parameters to the handle
  • The destructor takes care of releasing them

For the few properties that are lists (e.g., ContainerPortMapping), I created two backing vectors. One is for the WinRT objects that are used when interacting with the consumer, and the other is for backing the pointers passed to the C API.

For callbacks, we use events that are configured before calling Start() on the object, and we pass the C API a callback that invokes the event handler.

The tests are more or less a direct translation of the tests for the C API. The tests show some issues that I have not resolved yet.

Validation Steps Performed

Copilot AI review requested due to automatic review settings April 29, 2026 23:11

This comment was marked as outdated.

@benhillis
Copy link
Copy Markdown
Member

The feature/wsl-for-apps branch is now defunct. If your PR is still valid, please retarget the master branch. Reach out to @benhillis for help if needed.

florelis and others added 4 commits April 30, 2026 14:23
@florelis florelis changed the base branch from feature/wsl-for-apps to master April 30, 2026 21:41
Copilot AI review requested due to automatic review settings April 30, 2026 21:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI review requested due to automatic review settings May 11, 2026 00:20

This comment was marked as outdated.

@florelis florelis changed the title Implement WinRT / C# projection for the simple parts of the WSLC SDK API surface Implement WinRT / C# projection for the WSLC SDK API surface May 11, 2026
Copilot AI review requested due to automatic review settings May 11, 2026 15:59
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 46 out of 46 changed files in this pull request and generated 12 comments.

Comment on lines +165 to +169
auto context = ProgressCallbackHelper<winrt::Microsoft::WSL::Containers::ImageProgress>{co_await winrt::get_progress_token()};

auto pushStruct = GetStructPointer(options);
pushStruct->progressCallback = ImageProgressCallback;
pushStruct->progressCallbackContext = &context;
Comment on lines +132 to +135
m_settings = nullptr;

return *this;
}
// This takes ownership without increasing the ref count to account for the AddRef in ApplyCallbacksToSettings().
process.attach(static_cast<Process*>(context));

process->m_exitedEvent(*process, exitCode);
Comment on lines +29 to +32
if (options != InputStreamOptions::None)
{
winrt::throw_hresult(ERROR_NOT_SUPPORTED);
}
Comment on lines +99 to +103
if (m_cmdLine.Size() > 0)
{
auto argc = m_cmdLine.Size();
m_cmdLineStrings = StringArray{argc};
for (auto const& arg : m_cmdLine)
Comment on lines +347 to +351
// Positive: load a saved image tar and verify the image can be run
{
// Remote the image if it already exists
IGNORE_ERRORS(m_defaultSession.DeleteImage(L"hello-world:latest"));

Comment on lines +282 to +287

// Negative: Must throw if used used before Start()
{
auto session = WSLCSDK::Session::Create(settings);
VERIFY_THROWS_HR(std::ignore = session.Images(), E_ILLEGAL_METHOD_CALL);
}
Comment on lines +1496 to +1503
auto container = m_defaultSession.CreateContainer(containerSettings);
container.Start(WSLCSDK::ContainerStartFlags::Attach);

// The init process has now exited. Attempting to exec on a stopped container must fail.
auto execSettings = WSLCSDK::ProcessSettings();
execSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/echo", L"should-fail"}));

VERIFY_THROWS_HR(container.CreateProcess(execSettings).Start(), static_cast<HRESULT>(WSLC_E_CONTAINER_NOT_RUNNING));
Comment on lines +1488 to +1492
WSLC_TEST_METHOD(StopContainerWithInvalidSignal)
{
auto procSettings = WSLCSDK::ProcessSettings();
procSettings.CmdLine(winrt::single_threaded_vector<winrt::hstring>({L"/bin/sleep", L"10"}));

bool callbacksApplied = false;
if (m_initProcess)
{
callbacksApplied = m_initProcess->ApplyCallbacksToSettings(GetStructPointer(GetImplementation(m_settings)->InitProcess()));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants