-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement most IWeakReference[Source] boilerplate
- Loading branch information
1 parent
4332d52
commit 5ce046b
Showing
21 changed files
with
562 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import C_BINDINGS_MODULE | ||
|
||
internal let IID_IWeakReference: IID = IID(Data1: 0x00000037, Data2: 0x0000, Data3: 0x0000, Data4: (0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)) // 00000037-0000-0000-C000-000000000046 | ||
|
||
fileprivate extension IUnknownRef { | ||
func copyTo(_ riid: REFIID?, _ ppvObj: UnsafeMutablePointer<LPVOID?>?) -> HRESULT { | ||
self.borrow.pointee.lpVtbl.pointee.QueryInterface(self.borrow, riid, ppvObj) | ||
} | ||
} | ||
|
||
func makeWeakReference(_ object: AnyObject, _ result: UnsafeMutablePointer<UnsafeMutableRawPointer?>) throws { | ||
let wrapper = WeakReferenceWrapper(WeakReference(object)) | ||
try wrapper.toABI { | ||
_ = $0.pointee.lpVtbl.pointee.AddRef($0) | ||
result.pointee = UnsafeMutableRawPointer($0) | ||
} | ||
} | ||
|
||
fileprivate class WeakReference { | ||
public weak var target: AnyObject? | ||
public init(_ target: AnyObject) { | ||
self.target = target | ||
} | ||
} | ||
|
||
fileprivate class WeakReferenceWrapper: WinRTAbiBridgeWrapper<IWeakReferenceBridge> { | ||
init(_ weakReference: WeakReference){ | ||
super.init(IWeakReferenceBridge.makeAbi(), weakReference) | ||
} | ||
} | ||
|
||
fileprivate enum IWeakReferenceBridge: AbiBridge { | ||
typealias CABI = C_IWeakReference | ||
typealias SwiftProjection = WeakReference | ||
|
||
static func makeAbi() -> C_IWeakReference { | ||
return C_IWeakReference(lpVtbl: &IWeakReferenceVTable) | ||
} | ||
|
||
static func from(abi: ComPtr<C_IWeakReference>?) -> WeakReference? { | ||
fatalError("Not needed") | ||
} | ||
} | ||
|
||
fileprivate var IWeakReferenceVTable: C_IWeakReferenceVtbl = .init( | ||
QueryInterface: { pUnk, riid, ppvObject in | ||
guard let pUnk, let riid, let ppvObject else { return E_INVALIDARG } | ||
switch riid.pointee { | ||
case IID_IWeakReference: | ||
_ = pUnk.pointee.lpVtbl.pointee.AddRef(pUnk) | ||
return S_OK | ||
default: | ||
guard let obj = WeakReferenceWrapper.tryUnwrapFromBase(raw: pUnk) else { return E_NOINTERFACE } | ||
fatalError("\(#function): Not implemented: something like obj.QueryInterface") | ||
} | ||
}, | ||
AddRef: { WeakReferenceWrapper.addRef($0) }, | ||
Release: { WeakReferenceWrapper.release($0) }, | ||
Resolve: { Resolve($0, $1, $2) } | ||
) | ||
|
||
fileprivate func Resolve( | ||
_ this: UnsafeMutablePointer<C_IWeakReference>?, | ||
_ iid: UnsafePointer<GUID_Workaround>?, | ||
_ inspectable: UnsafeMutablePointer<UnsafeMutablePointer<C_IInspectable>?>?) -> HRESULT { | ||
guard let weakReference = WeakReferenceWrapper.tryUnwrapFrom(abi: ComPtr(this)) else { return E_FAIL } | ||
guard let iid, let inspectable else { return E_INVALIDARG } | ||
if let target = weakReference.target { | ||
_ = target | ||
_ = iid | ||
fatalError("\(#function): Not implemented: something like target.QueryInterface") | ||
} | ||
else { | ||
inspectable.pointee = nil | ||
return S_OK | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import C_BINDINGS_MODULE | ||
|
||
internal let IID_IWeakReferenceSource: IID = IID(Data1: 0x00000038, Data2: 0x0000, Data3: 0x0000, Data4: (0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)) // 00000038-0000-0000-C000-000000000046 | ||
|
||
fileprivate extension IUnknownRef { | ||
func copyTo(_ riid: REFIID?, _ ppvObj: UnsafeMutablePointer<LPVOID?>?) -> HRESULT { | ||
self.borrow.pointee.lpVtbl.pointee.QueryInterface(self.borrow, riid, ppvObj) | ||
} | ||
} | ||
|
||
func makeWeakReferenceSource(_ object: AnyObject, _ result: UnsafeMutablePointer<UnsafeMutableRawPointer?>) throws { | ||
let wrapper = WeakReferenceSourceWrapper(object) | ||
try wrapper.toABI { | ||
_ = $0.pointee.lpVtbl.pointee.AddRef($0) | ||
result.pointee = UnsafeMutableRawPointer($0) | ||
} | ||
} | ||
|
||
fileprivate class WeakReferenceSourceWrapper: WinRTAbiBridgeWrapper<IWeakReferenceSourceBridge> { | ||
init(_ object: AnyObject){ | ||
super.init(IWeakReferenceSourceBridge.makeAbi(), object) | ||
} | ||
} | ||
|
||
fileprivate enum IWeakReferenceSourceBridge: AbiBridge { | ||
typealias CABI = C_IWeakReferenceSource | ||
typealias SwiftProjection = AnyObject | ||
|
||
static func makeAbi() -> C_IWeakReferenceSource { | ||
return C_IWeakReferenceSource(lpVtbl: &IWeakReferenceSourceVTable) | ||
} | ||
|
||
static func from(abi: ComPtr<C_IWeakReferenceSource>?) -> AnyObject? { | ||
fatalError("Not needed") | ||
} | ||
} | ||
|
||
fileprivate var IWeakReferenceSourceVTable: C_IWeakReferenceSourceVtbl = .init( | ||
QueryInterface: { pUnk, riid, ppvObject in | ||
guard let pUnk, let riid, let ppvObject else { return E_INVALIDARG } | ||
switch riid.pointee { | ||
case IID_IWeakReferenceSource: | ||
_ = pUnk.pointee.lpVtbl.pointee.AddRef(pUnk) | ||
return S_OK | ||
default: | ||
guard let obj = WeakReferenceSourceWrapper.tryUnwrapFromBase(raw: pUnk) else { return E_NOINTERFACE } | ||
fatalError("\(#function): Not implemented: something like obj.QueryInterface") | ||
} | ||
}, | ||
AddRef: { WeakReferenceSourceWrapper.addRef($0) }, | ||
Release: { WeakReferenceSourceWrapper.release($0) }, | ||
GetWeakReference: { GetWeakReference($0, $1) } | ||
) | ||
|
||
fileprivate func GetWeakReference( | ||
_ this: UnsafeMutablePointer<C_IWeakReferenceSource>?, | ||
_ weakReference: UnsafeMutablePointer<UnsafeMutablePointer<C_IWeakReference>?>?) -> HRESULT { | ||
guard let object = WeakReferenceSourceWrapper.tryUnwrapFrom(abi: ComPtr(this)) else { return E_FAIL } | ||
guard let weakReference else { return E_INVALIDARG } | ||
do { | ||
var rawWeakReference: UnsafeMutableRawPointer? = nil | ||
try makeWeakReference(object, &rawWeakReference) | ||
weakReference.pointee = rawWeakReference?.bindMemory(to: C_IWeakReference.self, capacity: 1) | ||
return S_OK | ||
} catch { | ||
return E_FAIL | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import WinSDK | ||
import XCTest | ||
@_spi(WinRTInternal) import test_component | ||
import Ctest_component | ||
import Foundation | ||
|
||
class WeakReferenceTests : XCTestCase { | ||
class Target: IReferenceTarget { | ||
func method() {} | ||
} | ||
|
||
public func testCreateAndResolve() throws { | ||
let original = Target() | ||
let weakReferencer = WeakReferencer(original) | ||
let roundtrippedAny = try XCTUnwrap(weakReferencer.resolve()) | ||
let roundtripped = try XCTUnwrap(roundtrippedAny as? Target) | ||
XCTAssertIdentical(roundtripped, original) | ||
} | ||
|
||
public func testNotStrong() throws { | ||
var original: Target! = Target() | ||
let weakReferencer = WeakReferencer(original) | ||
original = nil | ||
XCTAssertNil(try weakReferencer.resolve()) | ||
} | ||
} | ||
|
||
var weakReferenceTests: [XCTestCaseEntry] = [ | ||
testCase([ | ||
("testCreateAndResolve", WeakReferenceTests.testCreateAndResolve), | ||
("testNotStrong", WeakReferenceTests.testNotStrong) | ||
]) | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.