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

Support IReference of structs and enums to T? #91

Merged
merged 1 commit into from
Mar 28, 2024
Merged
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
4 changes: 4 additions & 0 deletions Generator/Sources/ProjectionModel/SupportModules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ extension SupportModules.WinRT {
.chain([ .init(moduleName), .init("IReferenceUnboxingProjection"), .init(type.name) ])
}

public static func ireferenceUnboxingProjection(of projectionType: SwiftType) -> SwiftType {
.chain([ .init(moduleName), .init("IReferenceUnboxingProjection"), .init("Of", genericArgs: [ projectionType ]) ])
}

public static var winRTClassLoader: SwiftType { .chain(moduleName, "WinRTClassLoader") }
}

Expand Down
22 changes: 13 additions & 9 deletions Generator/Sources/ProjectionModel/SwiftProjection+types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -223,18 +223,22 @@ extension SwiftProjection {
}

private func getIReferenceTypeProjection(of type: BoundType) throws -> TypeProjection? {
let typeProjection = try getTypeProjection(type.asNode)
let projectionType: SwiftType
if type.definition.namespace == "System",
let primitiveType = WinRTPrimitiveType(fromSystemNamespaceType: type.definition.name) {
let typeProjection = try getTypeProjection(type.asNode)
return TypeProjection(
abiType: .optional(wrapped: .unsafeMutablePointer(to: .chain(abiModuleName, CAbi.ireferenceName))),
abiDefaultValue: .nil,
swiftType: .optional(wrapped: typeProjection.swiftType),
swiftDefaultValue: .nil,
projectionType: SupportModules.WinRT.ireferenceUnboxingProjection(of: primitiveType),
kind: .allocating)
projectionType = SupportModules.WinRT.ireferenceUnboxingProjection(of: primitiveType)
}
else {
projectionType = SupportModules.WinRT.ireferenceUnboxingProjection(of: typeProjection.projectionType)
}

return nil
return TypeProjection(
abiType: .optional(wrapped: .unsafeMutablePointer(to: .chain(abiModuleName, CAbi.ireferenceName))),
abiDefaultValue: .nil,
swiftType: .optional(wrapped: typeProjection.swiftType),
swiftDefaultValue: .nil,
projectionType: projectionType,
kind: .allocating)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import WindowsRuntime
import WinRTComponent
import XCTest

class BoxingTests: WinRTTestCase {
typealias CppBoxing = WinRTComponent.Boxing
class InspectableBoxingTests: WinRTTestCase {
typealias CppBoxing = WinRTComponent.InspectableBoxing
typealias SwiftBoxing = WindowsRuntime.IInspectableBoxing

func testRoundTripOfPrimitiveTypeWithIdentityProjection() throws {
Expand Down
26 changes: 26 additions & 0 deletions InteropTests/Tests/ReferenceBoxingTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import WindowsRuntime
import WinRTComponent
import XCTest

class ReferenceBoxingTests: WinRTTestCase {
func testRoundTripOfPrimitiveTypeWithIdentityProjection() throws {
let original = Int32(42)
XCTAssertEqual(try XCTUnwrap(ReferenceBoxing.boxInt32(original)), original)
XCTAssertEqual(try ReferenceBoxing.unboxInt32(Optional(original)), original)
XCTAssertThrowsError(try ReferenceBoxing.unboxInt32(nil))
}

func testRoundTripOfEnumType() throws {
let original = MinimalEnum.one
XCTAssertEqual(try XCTUnwrap(ReferenceBoxing.boxMinimalEnum(original)), original)
XCTAssertEqual(try ReferenceBoxing.unboxMinimalEnum(Optional(original)), original)
XCTAssertThrowsError(try ReferenceBoxing.unboxMinimalEnum(nil))
}

func testRoundTripOfStructType() throws {
let original = MinimalStruct(field: 42)
XCTAssertEqual(try XCTUnwrap(ReferenceBoxing.boxMinimalStruct(original)), original)
XCTAssertEqual(try ReferenceBoxing.unboxMinimalStruct(Optional(original)), original)
XCTAssertThrowsError(try ReferenceBoxing.unboxMinimalStruct(nil))
}
}
39 changes: 0 additions & 39 deletions InteropTests/WinRTComponent/Boxing.cpp

This file was deleted.

39 changes: 39 additions & 0 deletions InteropTests/WinRTComponent/InspectableBoxing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "pch.h"
#include "InspectableBoxing.h"
#include "InspectableBoxing.g.cpp"

namespace winrt::WinRTComponent::implementation
{
winrt::Windows::Foundation::IInspectable InspectableBoxing::BoxInt32(int32_t value)
{
return winrt::box_value(value);
}
int32_t InspectableBoxing::UnboxInt32(winrt::Windows::Foundation::IInspectable const& value)
{
return winrt::unbox_value<int32_t>(value);
}
winrt::Windows::Foundation::IInspectable InspectableBoxing::BoxString(hstring const& value)
{
return winrt::box_value(value);
}
hstring InspectableBoxing::UnboxString(winrt::Windows::Foundation::IInspectable const& value)
{
return winrt::unbox_value<hstring>(value);
}
winrt::Windows::Foundation::IInspectable InspectableBoxing::BoxMinimalEnum(winrt::WinRTComponent::MinimalEnum const& value)
{
return winrt::box_value(value);
}
winrt::WinRTComponent::MinimalEnum InspectableBoxing::UnboxMinimalEnum(winrt::Windows::Foundation::IInspectable const& value)
{
return winrt::unbox_value<winrt::WinRTComponent::MinimalEnum>(value);
}
winrt::Windows::Foundation::IInspectable InspectableBoxing::BoxMinimalStruct(winrt::WinRTComponent::MinimalStruct const& value)
{
return winrt::box_value(value);
}
winrt::WinRTComponent::MinimalStruct InspectableBoxing::UnboxMinimalStruct(winrt::Windows::Foundation::IInspectable const& value)
{
return winrt::unbox_value<winrt::WinRTComponent::MinimalStruct>(value);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#pragma once
#include "Boxing.g.h"
#include "InspectableBoxing.g.h"

namespace winrt::WinRTComponent::implementation
{
struct Boxing
struct InspectableBoxing
{
Boxing() = default;
InspectableBoxing() = default;

static winrt::Windows::Foundation::IInspectable BoxInt32(int32_t value);
static int32_t UnboxInt32(winrt::Windows::Foundation::IInspectable const& value);
Expand All @@ -19,7 +19,7 @@ namespace winrt::WinRTComponent::implementation
}
namespace winrt::WinRTComponent::factory_implementation
{
struct Boxing : BoxingT<Boxing, implementation::Boxing>
struct InspectableBoxing : InspectableBoxingT<InspectableBoxing, implementation::InspectableBoxing>
{
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import "MinimalTypes.idl";

namespace WinRTComponent
{
static runtimeclass Boxing
static runtimeclass InspectableBoxing
{
static IInspectable BoxInt32(Int32 value);
static Int32 UnboxInt32(IInspectable value);
Expand Down
34 changes: 34 additions & 0 deletions InteropTests/WinRTComponent/ReferenceBoxing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "pch.h"
#include "ReferenceBoxing.h"
#include "ReferenceBoxing.g.cpp"

namespace winrt::WinRTComponent::implementation
{
winrt::Windows::Foundation::IReference<int32_t> ReferenceBoxing::BoxInt32(int32_t value)
{
return { value };
}
int32_t ReferenceBoxing::UnboxInt32(winrt::Windows::Foundation::IReference<int32_t> const& value)
{
if (value == nullptr) throw winrt::hresult_invalid_argument();
return value.Value();
}
Windows::Foundation::IReference<winrt::WinRTComponent::MinimalEnum> ReferenceBoxing::BoxMinimalEnum(winrt::WinRTComponent::MinimalEnum const& value)
{
return { value };
}
winrt::WinRTComponent::MinimalEnum ReferenceBoxing::UnboxMinimalEnum(Windows::Foundation::IReference<winrt::WinRTComponent::MinimalEnum> const& value)
{
if (value == nullptr) throw winrt::hresult_invalid_argument();
return value.Value();
}
Windows::Foundation::IReference<winrt::WinRTComponent::MinimalStruct> ReferenceBoxing::BoxMinimalStruct(winrt::WinRTComponent::MinimalStruct const& value)
{
return { value };
}
winrt::WinRTComponent::MinimalStruct ReferenceBoxing::UnboxMinimalStruct(Windows::Foundation::IReference<winrt::WinRTComponent::MinimalStruct> const& value)
{
if (value == nullptr) throw winrt::hresult_invalid_argument();
return value.Value();
}
}
23 changes: 23 additions & 0 deletions InteropTests/WinRTComponent/ReferenceBoxing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once
#include "ReferenceBoxing.g.h"

namespace winrt::WinRTComponent::implementation
{
struct ReferenceBoxing
{
ReferenceBoxing() = default;

static winrt::Windows::Foundation::IReference<int32_t> BoxInt32(int32_t value);
static int32_t UnboxInt32(winrt::Windows::Foundation::IReference<int32_t> const& value);
static winrt::Windows::Foundation::IReference<winrt::WinRTComponent::MinimalEnum> BoxMinimalEnum(winrt::WinRTComponent::MinimalEnum const& value);
static winrt::WinRTComponent::MinimalEnum UnboxMinimalEnum(winrt::Windows::Foundation::IReference<winrt::WinRTComponent::MinimalEnum> const& value);
static winrt::Windows::Foundation::IReference<winrt::WinRTComponent::MinimalStruct> BoxMinimalStruct(winrt::WinRTComponent::MinimalStruct const& value);
static winrt::WinRTComponent::MinimalStruct UnboxMinimalStruct(winrt::Windows::Foundation::IReference<winrt::WinRTComponent::MinimalStruct> const& value);
};
}
namespace winrt::WinRTComponent::factory_implementation
{
struct ReferenceBoxing : ReferenceBoxingT<ReferenceBoxing, implementation::ReferenceBoxing>
{
};
}
15 changes: 15 additions & 0 deletions InteropTests/WinRTComponent/ReferenceBoxing.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import "MinimalTypes.idl";

namespace WinRTComponent
{
static runtimeclass ReferenceBoxing
{
static Windows.Foundation.IReference<Int32> BoxInt32(Int32 value);
static Int32 UnboxInt32(Windows.Foundation.IReference<Int32> value);
// Windows.Foundation.IReference<String> is illegal: "Invalid parameter to IReference or IReferenceArray"
static Windows.Foundation.IReference<MinimalEnum> BoxMinimalEnum(MinimalEnum value);
static MinimalEnum UnboxMinimalEnum(Windows.Foundation.IReference<MinimalEnum> value);
static Windows.Foundation.IReference<MinimalStruct> BoxMinimalStruct(MinimalStruct value);
static MinimalStruct UnboxMinimalStruct(Windows.Foundation.IReference<MinimalStruct> value);
};
}
17 changes: 12 additions & 5 deletions InteropTests/WinRTComponent/WinRTComponent.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@
<ClInclude Include="Arrays.h">
<DependentUpon>Arrays.idl</DependentUpon>
</ClInclude>
<ClInclude Include="Boxing.h">
<DependentUpon>Boxing.idl</DependentUpon>
<ClInclude Include="InspectableBoxing.h">
<DependentUpon>InspectableBoxing.idl</DependentUpon>
</ClInclude>
<ClInclude Include="DateTimes.h">
<DependentUpon>DateTimes.idl</DependentUpon>
Expand Down Expand Up @@ -154,6 +154,9 @@
<ClInclude Include="OverloadedSum.h">
<DependentUpon>OverloadedSum.idl</DependentUpon>
</ClInclude>
<ClInclude Include="ReferenceBoxing.h">
<DependentUpon>ReferenceBoxing.idl</DependentUpon>
</ClInclude>
<ClInclude Include="ReturnArgument.h">
<DependentUpon>ReturnArgument.idl</DependentUpon>
</ClInclude>
Expand All @@ -177,8 +180,8 @@
<ClCompile Include="Arrays.cpp">
<DependentUpon>Arrays.idl</DependentUpon>
</ClCompile>
<ClCompile Include="Boxing.cpp">
<DependentUpon>Boxing.idl</DependentUpon>
<ClCompile Include="InspectableBoxing.cpp">
<DependentUpon>InspectableBoxing.idl</DependentUpon>
</ClCompile>
<ClCompile Include="DateTimes.cpp">
<DependentUpon>DateTimes.idl</DependentUpon>
Expand Down Expand Up @@ -216,6 +219,9 @@
<ClCompile Include="OverloadedSum.cpp">
<DependentUpon>OverloadedSum.idl</DependentUpon>
</ClCompile>
<ClCompile Include="ReferenceBoxing.cpp">
<DependentUpon>ReferenceBoxing.idl</DependentUpon>
</ClCompile>
<ClCompile Include="ReturnArgument.cpp">
<DependentUpon>ReturnArgument.idl</DependentUpon>
</ClCompile>
Expand All @@ -231,7 +237,7 @@
</ItemGroup>
<ItemGroup>
<Midl Include="Arrays.idl" />
<Midl Include="Boxing.idl" />
<Midl Include="InspectableBoxing.idl" />
<Midl Include="DateTimes.idl" />
<Midl Include="Enums.idl" />
<Midl Include="Errors.idl" />
Expand All @@ -245,6 +251,7 @@
<Midl Include="ObjectReferencer.idl" />
<Midl Include="OutputArgument.idl" />
<Midl Include="OverloadedSum.idl" />
<Midl Include="ReferenceBoxing.idl" />
<Midl Include="ReturnArgument.idl" />
<Midl Include="Strings.idl" />
<Midl Include="Structs.idl" />
Expand Down
Loading