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

cache factories and use fast pass strings #142

Merged
merged 1 commit into from
Mar 1, 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
57 changes: 57 additions & 0 deletions swiftwinrt/Resources/CWinRT/CppInteropWorkaround.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ typedef GUID_Workaround UUID_Workaround;
// Functions depending on workaround types
typedef struct IUnknown_Workaround IUnknown_Workaround;
typedef struct IInspectable_Workaround IInspectable_Workaround;
typedef struct IActivationFactory_Workaround IActivationFactory_Workaround;
typedef struct IMarshal_Workaround IMarshal_Workaround;

#include <combaseapi.h>
Expand Down Expand Up @@ -66,6 +67,12 @@ inline HRESULT RoGetActivationFactory_Workaround(
#endif
}

// Since we can't define statically allocated arrays in swift, just use a large enough buffer to hold the data.
// In reality this could probably be closer to 128
struct StaticWCharArray_512 {
WCHAR Data[512];
};

//-------------------------------------------------------------------------------------------------
// Begin the great lie
// Everything below will unknowingly use Xxx_Workaround.
Expand All @@ -91,6 +98,8 @@ inline HRESULT RoGetActivationFactory_Workaround(
#define IInspectableVtbl IInspectableVtbl_Workaround
#define IMarshal IMarshal_Workaround
#define IMarshalVtbl IMarshalVtbl_Workaround
#define IActivationFactory IActivationFactory_Workaround
#define IActivationFactoryVtbl IActivationFactoryVtbl_Workaround

// iunknown.h
typedef struct IUnknownVtbl
Expand Down Expand Up @@ -234,4 +243,52 @@ typedef struct IMarshalVtbl
interface IMarshal
{
CONST_VTBL struct IMarshalVtbl *lpVtbl;
};

typedef struct IActivationFactoryVtbl
{
BEGIN_INTERFACE

DECLSPEC_XFGVIRT(IUnknown, QueryInterface)
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
__RPC__in IActivationFactory * This,
/* [in] */ __RPC__in REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void **ppvObject);

DECLSPEC_XFGVIRT(IUnknown, AddRef)
ULONG ( STDMETHODCALLTYPE *AddRef )(
__RPC__in IActivationFactory * This);

DECLSPEC_XFGVIRT(IUnknown, Release)
ULONG ( STDMETHODCALLTYPE *Release )(
__RPC__in IActivationFactory * This);

DECLSPEC_XFGVIRT(IInspectable, GetIids)
HRESULT ( STDMETHODCALLTYPE *GetIids )(
__RPC__in IActivationFactory * This,
/* [out] */ __RPC__out ULONG *iidCount,
/* [size_is][size_is][out] */ __RPC__deref_out_ecount_full_opt(*iidCount) IID **iids);

DECLSPEC_XFGVIRT(IInspectable, GetRuntimeClassName)
HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )(
__RPC__in IActivationFactory * This,
/* [out] */ __RPC__deref_out_opt HSTRING *className);

DECLSPEC_XFGVIRT(IInspectable, GetTrustLevel)
HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )(
__RPC__in IActivationFactory * This,
/* [out] */ __RPC__out TrustLevel *trustLevel);

DECLSPEC_XFGVIRT(IActivationFactory, ActivateInstance)
HRESULT ( STDMETHODCALLTYPE *ActivateInstance )(
__RPC__in IActivationFactory * This,
/* [out] */ __RPC__deref_out_opt IInspectable **instance);

END_INTERFACE
} IActivationFactoryVtbl;

interface IActivationFactory
{
CONST_VTBL struct IActivationFactoryVtbl *lpVtbl;
};
4 changes: 4 additions & 0 deletions swiftwinrt/Resources/Support/CppInteropWorkaround.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public typealias C_IInspectable = C_BINDINGS_MODULE.IInspectable_Workaround
public typealias C_IInspectableVtbl = C_BINDINGS_MODULE.IInspectableVtbl_Workaround
public typealias C_IMarshal = C_BINDINGS_MODULE.IMarshal_Workaround
public typealias C_IMarshalVtbl = C_BINDINGS_MODULE.IMarshalVtbl_Workaround
public typealias C_IActivationFactory = C_BINDINGS_MODULE.IActivationFactory_Workaround
public typealias C_IActivationFactoryVtbl = C_BINDINGS_MODULE.IActivationFactoryVtbl_Workaround
internal let CoCreateInstance = C_BINDINGS_MODULE.CoCreateInstance_Workaround
internal let UuidFromStringA = C_BINDINGS_MODULE.UuidFromStringA_Workaround
internal let RoActivateInstance = C_BINDINGS_MODULE.RoActivateInstance_Workaround
Expand All @@ -26,6 +28,8 @@ public typealias C_IInspectable = C_BINDINGS_MODULE.IInspectable
public typealias C_IInspectableVtbl = C_BINDINGS_MODULE.IInspectableVtbl
public typealias C_IMarshal = C_BINDINGS_MODULE.IMarshal
public typealias C_IMarshalVtbl = C_BINDINGS_MODULE.IMarshalVtbl
public typealias C_IActivationFactory = C_BINDINGS_MODULE.IActivationFactory
public typealias C_IActivationFactoryVtbl = C_BINDINGS_MODULE.IActivationFactoryVtbl
internal let CoCreateInstance = C_BINDINGS_MODULE.CoCreateInstance
internal let UuidFromStringA = C_BINDINGS_MODULE.UuidFromStringA
internal let RoActivateInstance = C_BINDINGS_MODULE.RoActivateInstance
Expand Down
2 changes: 1 addition & 1 deletion swiftwinrt/Resources/Support/PropertyValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import WinSDK
// Handwritten implementation for PropertyValue which *doesn't* try to do the IInspectable <-> Any mapping.
// This class is used by the AnyWrapper to create IInspectable instances from this subset of known Any values.
internal final class PropertyValue {
private static let _IPropertyValueStatics: IPropertyValueStatics = try! RoGetActivationFactory(HString("Windows.Foundation.PropertyValue"))
private static let _IPropertyValueStatics: IPropertyValueStatics = try! RoGetActivationFactory("Windows.Foundation.PropertyValue")

public static func createUInt8(_ value: UInt8) -> SUPPORT_MODULE.IInspectable {
let propertyValue = try! _IPropertyValueStatics.CreateUInt8Impl(value)
Expand Down
29 changes: 21 additions & 8 deletions swiftwinrt/Resources/Support/Runtime+Swift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,33 @@
import WinSDK
import C_BINDINGS_MODULE

public func RoGetActivationFactory<Factory: IInspectable>(_ activatableClassId: HString) throws -> Factory {
private var IID_IActivationFactory: SUPPORT_MODULE.IID {
.init(Data1: 0x00000035, Data2: 0x0000, Data3: 0x0000, Data4: ( 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 )) // 00000035-0000-0000-C000-000000000046
}

public class IActivationFactory: SUPPORT_MODULE.IInspectable {
override public class var IID: SUPPORT_MODULE.IID { IID_IActivationFactory }

public func ActivateInstance() throws -> SUPPORT_MODULE.IInspectable {
return try perform(as: C_IActivationFactory.self) { pThis in
let instance = try ComPtrs.initialize { instanceAbi in
try CHECKED(pThis.pointee.lpVtbl.pointee.ActivateInstance(pThis, &instanceAbi))
}
return .init(instance!)
}
}
}

public func RoGetActivationFactory<Factory: IInspectable>(_ activatableClassId: StaticString) throws -> Factory {
var iid = Factory.IID
let (factory) = try ComPtrs.initialize(to: C_IInspectable.self) { factoryAbi in
try CHECKED(RoGetActivationFactory(activatableClassId.get(), &iid, &factoryAbi))
try activatableClassId.withHStringRef { activatableClassIdHStr in
try CHECKED(RoGetActivationFactory(activatableClassIdHStr, &iid, &factoryAbi))
}
}
return try factory!.queryInterface()
}

public func RoActivateInstance<Instance: IInspectable>(_ activatableClassId: HString) throws -> Instance {
let (instance) = try ComPtrs.initialize { instanceAbi in
try CHECKED(RoActivateInstance(activatableClassId.get(), &instanceAbi))
}
return try instance!.queryInterface()
}

// ISwiftImplemented is a marker interface for code-gen types which are created by swift/winrt. It's used to QI
// an IUnknown VTABLE to see whether we can unwrap this type as a known swift object. The class is marked final
Expand Down
25 changes: 25 additions & 0 deletions swiftwinrt/Resources/Support/Swift+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,31 @@ extension String {
let pwszBuffer: PCWSTR = WindowsGetStringRawBuffer(hString.get(), &length)
self.init(decoding: UnsafeBufferPointer(start: pwszBuffer, count: Int(length)), as: UTF16.self)
}

public func withHStringRef(_ body: (HSTRING?) throws -> Void) rethrows {
try self.withCString(encodedAs: UTF16.self) {
var hString: HSTRING?
var header: HSTRING_HEADER = .init()
try CHECKED(WindowsCreateStringReference($0, UInt32(self.count), &header, &hString))
try body(hString)
}
}
}

extension StaticString {
public func withHStringRef(_ body: (HSTRING?) throws -> Void) rethrows {
var buffer: C_BINDINGS_MODULE.StaticWCharArray_512 = .init()
try withUnsafeMutableBytes(of: &buffer.Data) { (bytes:UnsafeMutableRawBufferPointer) in
let bytesPtr = bytes.assumingMemoryBound(to: WCHAR.self)
self.withUTF8Buffer { utf8buffer in
try! CHECKED(MultiByteToWideChar(UInt32(CP_UTF8), 0, utf8buffer.baseAddress, Int32(utf8buffer.count), bytesPtr.baseAddress, Int32(bytes.count)))
}
var hString: HSTRING?
var header: HSTRING_HEADER = .init()
try CHECKED(WindowsCreateStringReference(bytesPtr.baseAddress, UINT32(self.utf8CodeUnitCount), &header, &hString))
try body(hString)
}
}
}

extension Bool {
Expand Down
10 changes: 6 additions & 4 deletions swiftwinrt/code_writers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1920,7 +1920,7 @@ vtable);
{
interface_info factory_info{ factoryIface };
auto swift_name = get_swift_name(factory_info);
w.write("private static let %: %.% = try! RoGetActivationFactory(HString(\"%\"))\n",
w.write("private static let %: %.% = try! RoGetActivationFactory(\"%\")\n",
swift_name, abi_namespace(factoryIface), factory.type, get_full_type_name(type));
for (const auto& method : factoryIface->functions)
{
Expand All @@ -1941,10 +1941,12 @@ vtable);
{
auto base_class = type.base_class;

w.write("private static let _defaultFactory: %.IActivationFactory = try! RoGetActivationFactory(\"%\")\n",
w.support, get_full_type_name(type));
w.write("%public init() {\n", has_default_constructor(base_class) ? "override " : "");
{
auto indent = w.push_indent();
auto activateInstance = w.write_temp("try! RoActivateInstance(HString(\"%\"))", get_full_type_name(type));
auto activateInstance = "try! Self._defaultFactory.ActivateInstance()";
if (base_class)
{
w.write("super.init(fromAbi: %)\n", activateInstance);
Expand Down Expand Up @@ -1992,7 +1994,7 @@ public init<Composable: ComposableImpl>(
{
if (auto factoryIface = dynamic_cast<const interface_type*>(factory.type))
{
w.write("private static var _% : %.% = try! RoGetActivationFactory(HString(\"%\"))\n\n",
w.write("private static var _% : %.% = try! RoGetActivationFactory(\"%\")\n\n",
factory.type,
abi_namespace(factoryIface),
factory.type,
Expand Down Expand Up @@ -2277,7 +2279,7 @@ public init<Composable: ComposableImpl>(
static_info.attributed = true;

auto impl_name = get_swift_name(static_info);
w.write("private static let %: %.% = try! RoGetActivationFactory(HString(\"%\"))\n",
w.write("private static let %: %.% = try! RoGetActivationFactory(\"%\")\n",
impl_name,
abi_namespace(statics.type),
statics.type->swift_type_name(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ public final class PropertySet : WinRTClass, IObservableMap, IMap, IIterable, IP
override public func queryInterface(_ iid: test_component.IID) -> IUnknownRef? {
return super.queryInterface(iid)
}
private static let _defaultFactory: test_component.IActivationFactory = try! RoGetActivationFactory("Windows.Foundation.Collections.PropertySet")
override public init() {
super.init(try! RoActivateInstance(HString("Windows.Foundation.Collections.PropertySet")))
super.init(try! Self._defaultFactory.ActivateInstance())
}

private lazy var _IObservableMap: IObservableMapString_Any! = getInterfaceForCaching()
Expand Down Expand Up @@ -133,8 +134,9 @@ public final class StringMap : WinRTClass, IMap, IIterable, IObservableMap {
override public func queryInterface(_ iid: test_component.IID) -> IUnknownRef? {
return super.queryInterface(iid)
}
private static let _defaultFactory: test_component.IActivationFactory = try! RoGetActivationFactory("Windows.Foundation.Collections.StringMap")
override public init() {
super.init(try! RoActivateInstance(HString("Windows.Foundation.Collections.StringMap")))
super.init(try! Self._defaultFactory.ActivateInstance())
}

/// [Open Microsoft documentation](https://learn.microsoft.com/uwp/api/windows.foundation.collections.stringmap.lookup)
Expand Down Expand Up @@ -229,8 +231,9 @@ public final class ValueSet : WinRTClass, IObservableMap, IMap, IIterable, IProp
override public func queryInterface(_ iid: test_component.IID) -> IUnknownRef? {
return super.queryInterface(iid)
}
private static let _defaultFactory: test_component.IActivationFactory = try! RoGetActivationFactory("Windows.Foundation.Collections.ValueSet")
override public init() {
super.init(try! RoActivateInstance(HString("Windows.Foundation.Collections.ValueSet")))
super.init(try! Self._defaultFactory.ActivateInstance())
}

private lazy var _IObservableMap: IObservableMapString_Any! = getInterfaceForCaching()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public final class Deferral : WinRTClass, IClosable {
override public func queryInterface(_ iid: test_component.IID) -> IUnknownRef? {
return super.queryInterface(iid)
}
private static let _IDeferralFactory: __ABI_Windows_Foundation.IDeferralFactory = try! RoGetActivationFactory(HString("Windows.Foundation.Deferral"))
private static let _IDeferralFactory: __ABI_Windows_Foundation.IDeferralFactory = try! RoGetActivationFactory("Windows.Foundation.Deferral")
public init(_ handler: DeferralCompletedHandler!) {
super.init(try! Self._IDeferralFactory.CreateImpl(handler))
}
Expand Down Expand Up @@ -83,7 +83,7 @@ public final class MemoryBuffer : WinRTClass, IClosable, IMemoryBuffer {
override public func queryInterface(_ iid: test_component.IID) -> IUnknownRef? {
return super.queryInterface(iid)
}
private static let _IMemoryBufferFactory: __ABI_Windows_Foundation.IMemoryBufferFactory = try! RoGetActivationFactory(HString("Windows.Foundation.MemoryBuffer"))
private static let _IMemoryBufferFactory: __ABI_Windows_Foundation.IMemoryBufferFactory = try! RoGetActivationFactory("Windows.Foundation.MemoryBuffer")
public init(_ capacity: UInt32) {
super.init(try! Self._IMemoryBufferFactory.CreateImpl(capacity))
}
Expand Down Expand Up @@ -132,7 +132,7 @@ public final class Uri : WinRTClass, IStringable {
override public func queryInterface(_ iid: test_component.IID) -> IUnknownRef? {
return super.queryInterface(iid)
}
private static let _IUriEscapeStatics: __ABI_Windows_Foundation.IUriEscapeStatics = try! RoGetActivationFactory(HString("Windows.Foundation.Uri"))
private static let _IUriEscapeStatics: __ABI_Windows_Foundation.IUriEscapeStatics = try! RoGetActivationFactory("Windows.Foundation.Uri")
/// [Open Microsoft documentation](https://learn.microsoft.com/uwp/api/windows.foundation.uri.unescapecomponent)
public static func unescapeComponent(_ toUnescape: String) -> String {
return try! _IUriEscapeStatics.UnescapeComponentImpl(toUnescape)
Expand All @@ -143,7 +143,7 @@ public final class Uri : WinRTClass, IStringable {
return try! _IUriEscapeStatics.EscapeComponentImpl(toEscape)
}

private static let _IUriRuntimeClassFactory: __ABI_Windows_Foundation.IUriRuntimeClassFactory = try! RoGetActivationFactory(HString("Windows.Foundation.Uri"))
private static let _IUriRuntimeClassFactory: __ABI_Windows_Foundation.IUriRuntimeClassFactory = try! RoGetActivationFactory("Windows.Foundation.Uri")
public init(_ uri: String) {
super.init(try! Self._IUriRuntimeClassFactory.CreateUriImpl(uri))
}
Expand Down Expand Up @@ -289,7 +289,7 @@ public final class WwwFormUrlDecoder : WinRTClass, IIterable, IVectorView {
override public func queryInterface(_ iid: test_component.IID) -> IUnknownRef? {
return super.queryInterface(iid)
}
private static let _IWwwFormUrlDecoderRuntimeClassFactory: __ABI_Windows_Foundation.IWwwFormUrlDecoderRuntimeClassFactory = try! RoGetActivationFactory(HString("Windows.Foundation.WwwFormUrlDecoder"))
private static let _IWwwFormUrlDecoderRuntimeClassFactory: __ABI_Windows_Foundation.IWwwFormUrlDecoderRuntimeClassFactory = try! RoGetActivationFactory("Windows.Foundation.WwwFormUrlDecoder")
public init(_ query: String) {
super.init(try! Self._IWwwFormUrlDecoderRuntimeClassFactory.CreateWwwFormUrlDecoderImpl(query))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ public final class QueryOptions : WinRTClass {
super.init(fromAbi)
}

private static let _defaultFactory: test_component.IActivationFactory = try! RoGetActivationFactory("Windows.Storage.Search.QueryOptions")
override public init() {
super.init(try! RoActivateInstance(HString("Windows.Storage.Search.QueryOptions")))
super.init(try! Self._defaultFactory.ActivateInstance())
}

private static let _IQueryOptionsFactory: __ABI_Windows_Storage_Search.IQueryOptionsFactory = try! RoGetActivationFactory(HString("Windows.Storage.Search.QueryOptions"))
private static let _IQueryOptionsFactory: __ABI_Windows_Storage_Search.IQueryOptionsFactory = try! RoGetActivationFactory("Windows.Storage.Search.QueryOptions")
public init(_ query: CommonFileQuery, _ fileTypeFilter: AnyIIterable<String>!) {
super.init(try! Self._IQueryOptionsFactory.CreateCommonFileQueryImpl(query, fileTypeFilter))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ public final class Buffer : WinRTClass, IBufferByteAccess, IBuffer {
override public func queryInterface(_ iid: test_component.IID) -> IUnknownRef? {
return super.queryInterface(iid)
}
private static let _IBufferFactory: __ABI_Windows_Storage_Streams.IBufferFactory = try! RoGetActivationFactory(HString("Windows.Storage.Streams.Buffer"))
private static let _IBufferFactory: __ABI_Windows_Storage_Streams.IBufferFactory = try! RoGetActivationFactory("Windows.Storage.Streams.Buffer")
public init(_ capacity: UInt32) {
super.init(try! Self._IBufferFactory.CreateImpl(capacity))
}

private static let _IBufferStatics: __ABI_Windows_Storage_Streams.IBufferStatics = try! RoGetActivationFactory(HString("Windows.Storage.Streams.Buffer"))
private static let _IBufferStatics: __ABI_Windows_Storage_Streams.IBufferStatics = try! RoGetActivationFactory("Windows.Storage.Streams.Buffer")
/// [Open Microsoft documentation](https://learn.microsoft.com/uwp/api/windows.storage.streams.buffer.createcopyfrommemorybuffer)
public static func createCopyFromMemoryBuffer(_ input: test_component.AnyIMemoryBuffer!) -> Buffer! {
return try! _IBufferStatics.CreateCopyFromMemoryBufferImpl(input)
Expand Down
Loading
Loading