├── .github ├── actions │ └── setup-swift │ │ └── action.yml └── workflows │ ├── build-and-test.yml │ └── publish-release.yml ├── .gitignore ├── .vscode ├── settings.json └── tasks.json ├── Building.md ├── CMakeLists.txt ├── CMakePresets.json ├── CompilerCheck ├── Bug72724 │ ├── CMakeLists.txt │ ├── Definition.swift │ └── Import.swift └── CMakeLists.txt ├── Docs ├── How it works.md ├── Migration from thebrowsercompany's swift-winrt.md ├── Projecting Errors └── Projection Design.md ├── Generator ├── .vscode │ ├── settings.json │ └── tasks.json ├── CMakeLists.txt ├── CMakePresets.json ├── Dependencies │ ├── CMakeLists.txt │ ├── swift-argument-parser │ │ └── CMakeLists.txt │ ├── swift-collections │ │ └── CMakeLists.txt │ └── swift-dotnetmetadata │ │ └── CMakeLists.txt ├── NuGet │ ├── CMakeLists.txt │ ├── Create-Package.ps1 │ └── Package.nuspec ├── Package.resolved ├── Package.swift ├── Projection.schema.json ├── SPMPostBuild.ps1 ├── Sources │ ├── CMakeLists.txt │ ├── CodeWriters │ │ ├── C │ │ │ ├── CCallingConvention.swift │ │ │ ├── CEnumerant.swift │ │ │ ├── CParamDecl.swift │ │ │ ├── CSourceFileWriter.swift │ │ │ ├── CType.swift │ │ │ ├── CTypeDeclKind.swift │ │ │ └── CVariableDecl.swift │ │ ├── CMake │ │ │ ├── CMakeCommandArgument.swift │ │ │ ├── CMakeLibraryType.swift │ │ │ ├── CMakeListsWriter.swift │ │ │ └── CMakeVisibility.swift │ │ ├── CMakeLists.txt │ │ ├── FileTextOutputStream.swift │ │ ├── LineBasedTextOutputStream.swift │ │ └── Swift │ │ │ ├── SwiftAttribute.swift │ │ │ ├── SwiftDocumentationComment.swift │ │ │ ├── SwiftIdentifier.swift │ │ │ ├── SwiftImportKind.swift │ │ │ ├── SwiftOperatorLocation.swift │ │ │ ├── SwiftPackage+write.swift │ │ │ ├── SwiftPackage.swift │ │ │ ├── SwiftParameter.swift │ │ │ ├── SwiftType+write.swift │ │ │ ├── SwiftType.swift │ │ │ ├── SwiftVisibility.swift │ │ │ └── SyntaxWriters │ │ │ ├── DocumentationComments.swift │ │ │ ├── Members.swift │ │ │ ├── Protocols.swift │ │ │ ├── SourceFile.swift │ │ │ ├── Statements.swift │ │ │ ├── SyntaxWriters.swift │ │ │ └── TypeDeclarations.swift │ ├── ProjectionModel │ │ ├── ABIMethodKind.swift │ │ ├── CAbi │ │ │ ├── CAbi+COMInterfaceDecl.swift │ │ │ ├── CAbi+CTypes.swift │ │ │ ├── CAbi+writing.swift │ │ │ └── CAbi.swift │ │ ├── CMakeLists.txt │ │ ├── Casing.swift │ │ ├── ClassFactoryKind.swift │ │ ├── Module.swift │ │ ├── ParamBinding.swift │ │ ├── Projection+abi.swift │ │ ├── Projection+conversion.swift │ │ ├── Projection+documentation.swift │ │ ├── Projection+params.swift │ │ ├── Projection+types.swift │ │ ├── Projection.swift │ │ ├── SHA1.swift │ │ ├── String+prefixes.swift │ │ ├── SupportModules.swift │ │ ├── TypeBinding.swift │ │ ├── Unowned.swift │ │ ├── WinRTMethodKind.swift │ │ └── WinRTTypeDiscoverer.swift │ └── SwiftWinRT │ │ ├── CMakeLists.txt │ │ ├── CMakeOptions.swift │ │ ├── CommandLineArguments.swift │ │ ├── Extensions │ │ ├── CMakeLists.txt │ │ ├── WindowsFoundationCollections_IIterable_swift │ │ ├── WindowsFoundationCollections_IVectorView_swift │ │ ├── WindowsFoundationCollections_IVector_swift │ │ ├── WindowsFoundation_IAsyncActionWithProgress_swift │ │ ├── WindowsFoundation_IAsyncAction_swift │ │ ├── WindowsFoundation_IAsyncOperationWithProgress_swift │ │ ├── WindowsFoundation_IAsyncOperation_swift │ │ ├── WindowsFoundation_IMemoryBufferReference_swift │ │ ├── WindowsFoundation_IMemoryBuffer_swift │ │ ├── WindowsFoundation_MemoryBuffer_swift │ │ ├── WindowsStorageStreams_Buffer_swift │ │ └── WindowsStorageStreams_IBuffer_swift │ │ ├── Filter.swift │ │ ├── ProjectionConfig.swift │ │ ├── SPMOptions.swift │ │ ├── Writing │ │ ├── ABIBinding.swift │ │ ├── ABIModule.swift │ │ ├── COMImportClass.swift │ │ ├── COMInteropExtension.swift │ │ ├── ClassDefinition.swift │ │ ├── EnumDefinition.swift │ │ ├── ExeManifest.swift │ │ ├── InterfaceDefinition.swift │ │ ├── MemberDefinition.swift │ │ ├── NamespaceModules.swift │ │ ├── NonthrowingProperties.swift │ │ ├── SecondaryInterfaces.swift │ │ ├── SourcePreamble.swift │ │ ├── StructDefinition.swift │ │ ├── SwiftPackageFile.swift │ │ ├── TypeDefinition.swift │ │ └── VirtualTable.swift │ │ ├── createProjection.swift │ │ ├── main.swift │ │ └── writeProjectionFiles.swift ├── Tests │ ├── LineBasedTextOutputStreamTests.swift │ └── SwiftSyntaxWriterTests.swift └── mscorlib │ └── CMakeLists.txt ├── InteropTests ├── .vscode │ └── tasks.json ├── CMakeLists.txt ├── CMakePresets.json ├── Package.swift ├── SPMPrebuild.ps1 ├── Tests │ ├── ActivationFactoryResolutionTests.swift │ ├── ActivationFactoryTests.swift │ ├── ArrayTests.swift │ ├── Asserts.swift │ ├── AsyncTests.swift │ ├── BuiltInConformancesTests.swift │ ├── ByteBufferTests.swift │ ├── ClassInheritanceTests.swift │ ├── CollectionTests.swift │ ├── DateTimeTests.swift │ ├── DeprecationTests.swift │ ├── EnumTests.swift │ ├── ErrorTests.swift │ ├── EventTests.swift │ ├── FlatModuleTests.swift │ ├── InspectableBoxingTests.swift │ ├── InterfaceImplementationTests.swift │ ├── LifetimeTests.swift │ ├── NamespaceModuleTests.swift │ ├── NullValueTests.swift │ ├── NumbersTests.swift │ ├── ObjectExportingTests.swift │ ├── OverloadingTests.swift │ ├── PropertyTests.swift │ ├── ReferenceBoxingTests.swift │ ├── StringTests.swift │ ├── StructTests.swift │ ├── ValueOutParamRoundtripTests.swift │ ├── ValueReturnRoundtripTests.swift │ ├── WeakReferenceTests.swift │ └── WinRTTestCase.swift └── WinRTComponent │ ├── .gitignore │ ├── CMakeLists.txt │ ├── CMakePresets.json │ ├── Dll │ ├── Arrays.cpp │ ├── ByteBuffers.cpp │ ├── CMakeLists.txt │ ├── ClassInheritance.cpp │ ├── Collections.cpp │ ├── DateTimes.cpp │ ├── DeprecatedClass.cpp │ ├── DestructionCallback.cpp │ ├── Errors.cpp │ ├── Events.cpp │ ├── ForCustomActivationFactoryResolution.cpp │ ├── InspectableBoxing.cpp │ ├── Int32Global.cpp │ ├── Int32Wrapper.cpp │ ├── InterfaceCasting.cpp │ ├── ManualAsyncOperation.cpp │ ├── MinimalClass.cpp │ ├── MinimalInterfaceFactory.cpp │ ├── NullValues.cpp │ ├── Numbers.cpp │ ├── ObjectReferencer.cpp │ ├── OutputArgument.cpp │ ├── OverloadedSum.cpp │ ├── ReferenceBoxing.cpp │ ├── ReturnArgument.cpp │ ├── ShadowingConstructors.cpp │ ├── Strings.cpp │ ├── Structs.cpp │ ├── SwiftAttributes.cpp │ ├── WeakReferencer.cpp │ ├── WinRTComponent.def │ └── pch.h │ ├── GenerateProjection.cmake │ ├── Projection.json │ └── WinMD │ ├── Arrays.idl │ ├── ByteBuffers.idl │ ├── CMakeLists.txt │ ├── ClassInheritance.idl │ ├── Collections.idl │ ├── DateTimes.idl │ ├── Deprecation.idl │ ├── DestructionCallback.idl │ ├── DocumentationComments.idl │ ├── Enums.idl │ ├── Errors.idl │ ├── Events.idl │ ├── ForCustomActivationFactoryResolution.idl │ ├── IExposeObservableVector.idl │ ├── IMultiGenericInstantiation.idl │ ├── IMultiOutParams.idl │ ├── InspectableBoxing.idl │ ├── Int32Wrapper.idl │ ├── InterfaceCasting.idl │ ├── ManualAsyncOperation.idl │ ├── MinimalTypes.idl │ ├── NullValues.idl │ ├── Numbers.idl │ ├── ObjectReferencer.idl │ ├── OutputArgument.idl │ ├── OverloadedSum.idl │ ├── ReferenceBoxing.idl │ ├── ReturnArgument.idl │ ├── ShadowingConstructors.idl │ ├── Strings.idl │ ├── Structs.idl │ ├── SwiftAttributes.idl │ ├── WeakReferencer.idl │ └── WinRTComponent.xml ├── License.txt ├── Package.swift ├── Readme.md └── Support ├── CMakeLists.txt ├── Readme.md ├── Sources ├── ABIBindings │ ├── ABIBinding.swift │ ├── BoolBinding.swift │ ├── CMakeLists.txt │ ├── CStyleEnum.swift │ ├── CStyleEnumBinding.swift │ ├── IdentityBinding.swift │ ├── NumericBinding.swift │ ├── PODBinding.swift │ └── WideCharBinding.swift ├── CMakeLists.txt ├── COM │ ├── ABIBindings.swift │ ├── CMakeLists.txt │ ├── COMAggregableBase.swift │ ├── COMBinding.swift │ ├── COMDelegatingTearOff.swift │ ├── COMEmbedderEx.swift │ ├── COMEmbedding+statics.swift │ ├── COMEmbedding.swift │ ├── COMError+SwiftErrorInfo.swift │ ├── COMError+createErrorInfo.swift │ ├── COMError.swift │ ├── COMExportBase.swift │ ├── COMImplements.swift │ ├── COMImport.swift │ ├── COMInterop.swift │ ├── COMReference+Optional.swift │ ├── COMReference.swift │ ├── COMTearOffBase.swift │ ├── COMTwoWayBinding.swift │ ├── FreeThreadedMarshal.swift │ ├── NullResult.swift │ ├── Projection │ │ ├── BStrBinding.swift │ │ ├── COMArray.swift │ │ ├── GUID.swift │ │ ├── HResult+getMessage.swift │ │ ├── HResult.swift │ │ ├── HResultBinding.swift │ │ ├── IAgileObject.swift │ │ ├── ICreateErrorInfo.swift │ │ ├── IErrorInfo.swift │ │ ├── ISupportErrorInfo.swift │ │ └── IUnknown.swift │ ├── SupportErrorInfoForAllInterfaces.swift │ ├── VirtualTablePointer.swift │ └── comIdentical.swift ├── COM_ABI │ ├── CMakeLists.txt │ ├── combaseapi.c │ ├── include │ │ ├── SWRT │ │ │ ├── COMEmbedding.h │ │ │ ├── modules │ │ │ │ └── COM.h │ │ │ └── winapi │ │ │ │ ├── BaseTsd.h │ │ │ │ ├── combaseapi.h │ │ │ │ ├── guiddef.h │ │ │ │ ├── oaidl.h │ │ │ │ ├── objidl.h │ │ │ │ ├── oleauto.h │ │ │ │ ├── unknwn.h │ │ │ │ └── wtypes.h │ │ └── module.modulemap │ └── oleauto.c ├── WindowsRuntime │ ├── ActivationFactoryResolver.swift │ ├── AsyncAwaiter.swift │ ├── BindingProtocols+extensions.swift │ ├── BindingProtocols.swift │ ├── CMakeLists.txt │ ├── ClosedEnum.swift │ ├── ComposableClass.swift │ ├── EventInvocationList.swift │ ├── EventRegistration.swift │ ├── ExportedDelegate.swift │ ├── IInspectableVirtualTable.swift │ ├── IReferenceToOptionalBinding.swift │ ├── ModuleReexports.swift │ ├── Projection │ │ ├── ArrayBinding.swift │ │ ├── Char16.swift │ │ ├── EventRegistrationToken.swift │ │ ├── HString.swift │ │ ├── IActivationFactory.swift │ │ ├── IBufferByteAccess.swift │ │ ├── IInspectable.swift │ │ ├── ILanguageExceptionErrorInfo.swift │ │ ├── ILanguageExceptionErrorInfo2.swift │ │ ├── IMemoryBufferByteAccess.swift │ │ ├── IRestrictedErrorInfo.swift │ │ ├── IWeakReference.swift │ │ ├── IWeakReferenceSource.swift │ │ ├── PrimitiveBindings.swift │ │ ├── Readme.md │ │ ├── TrustLevel.swift │ │ └── WindowsFoundation │ │ │ ├── Readme.md │ │ │ ├── WindowsFoundation_DateTime.swift │ │ │ ├── WindowsFoundation_IPropertyValue.swift │ │ │ ├── WindowsFoundation_IReference.swift │ │ │ ├── WindowsFoundation_IReferenceArray.swift │ │ │ ├── WindowsFoundation_IStringable.swift │ │ │ ├── WindowsFoundation_Point.swift │ │ │ ├── WindowsFoundation_PropertyType.swift │ │ │ ├── WindowsFoundation_Rect.swift │ │ │ ├── WindowsFoundation_Size.swift │ │ │ └── WindowsFoundation_TimeSpan.swift │ ├── PropertyValueStatics.swift │ ├── ReferenceArrayImpl.swift │ ├── ReferenceImpl.swift │ ├── SwiftWrapperFactory.swift │ ├── WeakReference.swift │ ├── WinRTError+LanguageException.swift │ ├── WinRTError.swift │ ├── WinRTExportBase.swift │ ├── WinRTImport.swift │ ├── WinRTInitialization.swift │ ├── WinRTTearOffBase.swift │ ├── createIReference.swift │ └── winrtIdentical.swift └── WindowsRuntime_ABI │ ├── CMakeLists.txt │ ├── include │ ├── SWRT │ │ ├── modules │ │ │ └── WindowsRuntime.h │ │ └── winapi │ │ │ ├── activation.h │ │ │ ├── eventtoken.h │ │ │ ├── inspectable.h │ │ │ ├── memorybuffer.h │ │ │ ├── restrictederrorinfo.h │ │ │ ├── roapi.h │ │ │ ├── robuffer.h │ │ │ ├── roerrorapi.h │ │ │ ├── weakreference.h │ │ │ ├── windows.foundation.h │ │ │ ├── windows.foundation.ireference.h │ │ │ └── winstring.h │ └── module.modulemap │ ├── roapi.c │ ├── roerrorapi.c │ └── winstring.c └── Tests ├── ABI └── include │ ├── SWRT_ICOMTest.h │ ├── SWRT_ICOMTest2.h │ ├── SWRT_IWinRTTest.h │ └── module.modulemap └── Tests ├── COMExportTests.swift ├── COMExportTests.testSecondaryInterfaceImplementerIsClosure.swift ├── HResultTests.swift ├── HStringTests.swift ├── IReferenceTests.swift ├── IReferenceToOptionalTests.swift ├── Support ├── ICOMTest.swift ├── ICOMTest2.swift ├── IWinRTTest.swift └── WinRTTestCase.swift └── WinRTExportTests.swift /.github/actions/setup-swift/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup Swift 2 | description: Installs dependencies and setups the environment for building Swift code on Windows. 3 | inputs: 4 | arch: 5 | description: The architecture to build for 6 | required: false 7 | default: '' 8 | vsdevenv: 9 | description: Setup a Visual Studio Development Environment 10 | required: false 11 | default: 'true' 12 | runs: 13 | using: "composite" 14 | 15 | steps: 16 | - name: Figure out arch 17 | id: arch 18 | if: inputs.vsdevenv == 'true' 19 | shell: pwsh 20 | env: 21 | INPUT_ARCH: ${{ inputs.arch }} 22 | run: | 23 | $HostArch = $Env:PROCESSOR_ARCHITECTURE.ToLowerInvariant() 24 | $TargetArch = $Env:INPUT_ARCH 25 | if (!$TargetArch) { $TargetArch = $HostArch } 26 | Add-Content -Path $Env:GITHUB_OUTPUT -Value "host=$HostArch" -Encoding utf8 27 | Add-Content -Path $Env:GITHUB_OUTPUT -Value "target=$TargetArch" -Encoding utf8 28 | 29 | - name: Setup Visual Studio Development Environment 30 | if: inputs.vsdevenv == 'true' 31 | uses: compnerd/gha-setup-vsdevenv@main 32 | with: 33 | host_arch: ${{ steps.arch.outputs.host }} 34 | arch: ${{ steps.arch.outputs.target }} 35 | winsdk: 10.0.22621.0 # GitHub runners have 10.0.26100.0 which regresses Swift's ucrt module 36 | 37 | - name: Install Swift 38 | uses: compnerd/gha-setup-swift@81f383b35a86e6e966de139be25b451d4f7dd953 # The next main commit breaks our %Path% 39 | with: 40 | branch: swift-5.10.1-release 41 | tag: 5.10.1-RELEASE 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | launch.json 2 | .build/ 3 | build/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "swift.autoGenerateLaunchConfigurations": false, 3 | "C_Cpp.autoAddFileAssociations": false, 4 | "cmake.automaticReconfigure": true, 5 | "cmake.useCMakePresets": "always", 6 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "Build Support Module (SPM)", 6 | "type": "swift", 7 | "args": [ 8 | "build", 9 | "--build-tests", 10 | "-Xlinker", 11 | "-debug:dwarf" 12 | ], 13 | "cwd": ".", 14 | "disableTaskQueue": true, 15 | "problemMatcher": [ 16 | "$swiftc" 17 | ], 18 | "group": { 19 | "kind": "build" 20 | }, 21 | "presentation": { 22 | "clear": true, 23 | "revealProblems": "onProblem" 24 | } 25 | }, 26 | { 27 | "label": "Build (CMake)", 28 | "type": "cmake", 29 | "command": "build", 30 | "preset": "${command:cmake.activeBuildPresetName}", 31 | "problemMatcher": [ "$swiftc" ], 32 | "group": { 33 | "kind": "build" 34 | }, 35 | "presentation": { 36 | "clear": true, 37 | "revealProblems": "onProblem" 38 | } 39 | }, 40 | { 41 | "label": "Configure (CMake)", 42 | "type": "cmake", 43 | "command": "configure", 44 | "preset": "${command:cmake.activeConfigurePresetName}", 45 | } 46 | ] 47 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21.0) 2 | 3 | project(SwiftWinRT LANGUAGES C Swift) 4 | 5 | if("$ENV{WindowsSDKVersion}" STREQUAL "" OR "$ENV{VSCMD_ARG_TGT_ARCH}" STREQUAL "") 6 | message(FATAL_ERROR "The CMake build requires the environment from a Visual Studio Developer Command Prompt.") 7 | endif() 8 | 9 | if("${CMAKE_EXPORT_COMPILE_COMMANDS}" STREQUAL "") 10 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 11 | endif() 12 | 13 | add_subdirectory(CompilerCheck) 14 | 15 | # Building InteropTests will require running the code generator, 16 | # so we configure and build it as a subproject. 17 | message(STATUS "Configuring Generator as subproject...") 18 | execute_process( 19 | COMMAND ${CMAKE_COMMAND} 20 | -S "${CMAKE_CURRENT_SOURCE_DIR}/Generator" 21 | -B "${CMAKE_CURRENT_BINARY_DIR}/Generator" 22 | -G "${CMAKE_GENERATOR}" 23 | -D "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" 24 | -D "CMAKE_C_COMPILER=${CMAKE_C_COMPILER}" 25 | -D "CMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG}" 26 | -D "CMAKE_Swift_COMPILER=${CMAKE_Swift_COMPILER}" 27 | -D "CMAKE_Swift_FLAGS_DEBUG=${CMAKE_Swift_FLAGS_DEBUG}" 28 | -D "CMAKE_EXPORT_COMPILE_COMMANDS=${CMAKE_EXPORT_COMPILE_COMMANDS}" 29 | COMMAND_ERROR_IS_FATAL ANY) 30 | 31 | message(STATUS "Building Generator as subproject...") 32 | execute_process( 33 | COMMAND ${CMAKE_COMMAND} --build "${CMAKE_CURRENT_BINARY_DIR}/Generator" 34 | COMMAND_ERROR_IS_FATAL ANY) 35 | 36 | add_subdirectory(Support) 37 | 38 | # Now build InteropTests, which depends on SWIFTWINRT_EXE 39 | set(SWIFTWINRT_EXE "${CMAKE_CURRENT_BINARY_DIR}/Generator/SwiftWinRT.exe") 40 | add_subdirectory(InteropTests) 41 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 21, 6 | "patch": 0 7 | }, 8 | "configurePresets": [ 9 | { 10 | "name": "debug", 11 | "displayName": "Debug", 12 | "generator": "Ninja", 13 | "binaryDir": "${sourceDir}/build/debug", 14 | "cacheVariables": { 15 | "CMAKE_BUILD_TYPE": "Debug", 16 | "CMAKE_C_COMPILER": "clang", 17 | "CMAKE_C_FLAGS_DEBUG": "-O0 -gdwarf -DNDEBUG", 18 | "CMAKE_Swift_FLAGS_DEBUG": "-DDEBUG -Onone -Xfrontend -g -Xfrontend -debug-info-format=dwarf -use-ld=lld -Xlinker -debug:dwarf" 19 | } 20 | } 21 | ], 22 | "buildPresets": [ 23 | { 24 | "name": "debug", 25 | "displayName": "Debug", 26 | "configurePreset": "debug" 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /CompilerCheck/Bug72724/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21.0) 2 | project(ImportTypealiasCorrectness LANGUAGES Swift) 3 | add_library(Definition STATIC Definition.swift) 4 | add_library(Import STATIC Import.swift) 5 | target_link_libraries(Import PRIVATE Definition) -------------------------------------------------------------------------------- /CompilerCheck/Bug72724/Definition.swift: -------------------------------------------------------------------------------- 1 | public protocol P {} 2 | public typealias AnyP = any P -------------------------------------------------------------------------------- /CompilerCheck/Bug72724/Import.swift: -------------------------------------------------------------------------------- 1 | import typealias Definition.AnyP -------------------------------------------------------------------------------- /CompilerCheck/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Determine the status of https://github.com/swiftlang/swift/issues/72724 with the current Swift toolchain. 2 | message(STATUS "Checking if Swift compiler exhibits bug 72724...") 3 | execute_process( 4 | COMMAND "${CMAKE_COMMAND}" 5 | -S "${CMAKE_CURRENT_SOURCE_DIR}/Bug72724" 6 | -B "${CMAKE_CURRENT_BINARY_DIR}/Bug72724" 7 | -G "${CMAKE_GENERATOR}" 8 | -D "CMAKE_Swift_COMPILER=${CMAKE_Swift_COMPILER}" 9 | OUTPUT_QUIET 10 | COMMAND_ERROR_IS_FATAL ANY) 11 | 12 | execute_process( 13 | COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_CURRENT_BINARY_DIR}/Bug72724" 14 | OUTPUT_QUIET 15 | RESULT_VARIABLE BUILD_RESULT) 16 | 17 | if("${BUILD_RESULT}" STREQUAL "0") 18 | set(SWIFT_BUG_72724 "0" PARENT_SCOPE) 19 | else() 20 | set(SWIFT_BUG_72724 "1" PARENT_SCOPE) 21 | endif() -------------------------------------------------------------------------------- /Generator/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cmake.automaticReconfigure": true, 3 | "cmake.configureOnOpen": true, 4 | "cmake.useCMakePresets": "always", 5 | "swift.autoGenerateLaunchConfigurations": false, 6 | "search.exclude": { 7 | "**/.build/**": true, 8 | "**/build/**": true 9 | }, 10 | "files.associations": { 11 | "*_swift": "swift" 12 | } 13 | } -------------------------------------------------------------------------------- /Generator/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "Build Debug (SPM)", 6 | "type": "swift", 7 | "args": [ 8 | "build", 9 | "--build-tests", 10 | "-Xlinker", 11 | "-debug:dwarf" 12 | ], 13 | "disableTaskQueue": true, 14 | "problemMatcher": [ 15 | "$swiftc" 16 | ], 17 | "group": { 18 | "kind": "build", 19 | "isDefault": true 20 | }, 21 | "presentation": { 22 | "clear": true, 23 | "revealProblems": "onProblem" 24 | } 25 | }, 26 | { 27 | "label": "Build Release (SPM)", 28 | "type": "swift", 29 | "args": [ 30 | "build", 31 | "-c", 32 | "release" 33 | ], 34 | "disableTaskQueue": true, 35 | "problemMatcher": [ 36 | "$swiftc" 37 | ], 38 | "group": { 39 | "kind": "build" 40 | }, 41 | "presentation": { 42 | "clear": true, 43 | "revealProblems": "onProblem" 44 | } 45 | }, 46 | { 47 | "label": "Build Debug (CMake)", 48 | "type": "cmake", 49 | "command": "build", 50 | "preset": "${command:cmake.activeBuildPresetName}", 51 | "problemMatcher": [ 52 | "$swiftc" 53 | ], 54 | "group": { 55 | "kind": "build" 56 | }, 57 | "presentation": { 58 | "clear": true, 59 | "revealProblems": "onProblem" 60 | } 61 | } 62 | ] 63 | } -------------------------------------------------------------------------------- /Generator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21.0) 2 | 3 | project(SwiftWinRT LANGUAGES C Swift) 4 | 5 | if("${CMAKE_EXPORT_COMPILE_COMMANDS}" STREQUAL "") 6 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 7 | endif() 8 | 9 | add_subdirectory(Dependencies) 10 | 11 | set(GENERATOR_STAGING_DIR "${CMAKE_CURRENT_BINARY_DIR}") 12 | add_subdirectory(Sources) 13 | add_subdirectory(mscorlib) 14 | 15 | add_subdirectory(NuGet) -------------------------------------------------------------------------------- /Generator/CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 21, 6 | "patch": 0 7 | }, 8 | "configurePresets": [ 9 | { 10 | "name": "debug", 11 | "displayName": "Debug", 12 | "generator": "Ninja", 13 | "binaryDir": "${sourceDir}/build/debug", 14 | "cacheVariables": { 15 | "CMAKE_BUILD_TYPE": "Debug", 16 | "CMAKE_C_COMPILER": "clang", 17 | "CMAKE_C_FLAGS_DEBUG": "-O0 -gdwarf -DNDEBUG", 18 | "CMAKE_Swift_FLAGS_DEBUG": "-DDEBUG -Onone -Xfrontend -g -Xfrontend -debug-info-format=dwarf -use-ld=lld -Xlinker -debug:dwarf" 19 | } 20 | }, 21 | { 22 | "name": "release", 23 | "displayName": "Release", 24 | "generator": "Ninja", 25 | "binaryDir": "${sourceDir}/build/release", 26 | "cacheVariables": { 27 | "CMAKE_BUILD_TYPE": "RelWithDebInfo", 28 | "CMAKE_C_COMPILER": "clang", 29 | "CMAKE_C_FLAGS_RELWITHDEBINFO": "-O2 -g -DNDEBUG", 30 | "CMAKE_Swift_FLAGS_RELWITHDEBINFO": "-O -DNDEBUG -Xfrontend -g -Xfrontend -debug-info-format=codeview -use-ld=lld -Xlinker -debug" 31 | } 32 | } 33 | ], 34 | "buildPresets": [ 35 | { 36 | "name": "debug", 37 | "displayName": "Debug", 38 | "configurePreset": "debug" 39 | }, 40 | { 41 | "name": "release", 42 | "displayName": "Release", 43 | "configurePreset": "release" 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /Generator/Dependencies/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | 3 | add_compile_options( 4 | $<$:-suppress-remarks> 5 | $<$:-suppress-warnings>) 6 | 7 | add_subdirectory(swift-argument-parser) 8 | add_subdirectory(swift-collections) 9 | add_subdirectory(swift-dotnetmetadata) 10 | set(WINMDCORLIB_DIR "${WINMDCORLIB_DIR}" PARENT_SCOPE) -------------------------------------------------------------------------------- /Generator/Dependencies/swift-argument-parser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FetchContent_Declare( 2 | swift-argument-parser 3 | GIT_REPOSITORY https://github.com/apple/swift-argument-parser.git 4 | GIT_TAG 8f4d2753f0e4778c76d5f05ad16c74f707390531 # 1.2.3 5 | SOURCE_SUBDIR "don't use cmakelists") 6 | FetchContent_MakeAvailable(swift-argument-parser) 7 | 8 | file(GLOB_RECURSE SOURCES ${swift-argument-parser_SOURCE_DIR}/Sources/ArgumentParserToolInfo/*.swift) 9 | add_library(ArgumentParserToolInfo STATIC ${SOURCES}) 10 | 11 | file(GLOB_RECURSE SOURCES ${swift-argument-parser_SOURCE_DIR}/Sources/ArgumentParser/*.swift) 12 | add_library(ArgumentParser STATIC ${SOURCES}) 13 | target_link_libraries(ArgumentParser PRIVATE ArgumentParserToolInfo) -------------------------------------------------------------------------------- /Generator/Dependencies/swift-collections/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FetchContent_Declare( 2 | swift-collections 3 | GIT_REPOSITORY https://github.com/apple/swift-collections.git 4 | GIT_TAG d029d9d39c87bed85b1c50adee7c41795261a192 # 1.0.6 5 | SOURCE_SUBDIR "don't use cmakelists") 6 | FetchContent_MakeAvailable(swift-collections) 7 | 8 | file(GLOB_RECURSE SOURCES ${swift-collections_SOURCE_DIR}/Sources/DequeModule/*.swift) 9 | add_library(DequeModule STATIC ${SOURCES}) 10 | 11 | file(GLOB_RECURSE SOURCES ${swift-collections_SOURCE_DIR}/Sources/OrderedCollections/*.swift) 12 | add_library(OrderedCollections STATIC ${SOURCES}) 13 | 14 | file(GLOB_RECURSE SOURCES ${swift-collections_SOURCE_DIR}/Sources/Collections/*.swift) 15 | add_library(Collections STATIC ${SOURCES}) 16 | target_link_libraries(Collections PRIVATE DequeModule OrderedCollections) -------------------------------------------------------------------------------- /Generator/Dependencies/swift-dotnetmetadata/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FetchContent_Declare( 2 | swift-dotnetmetadata 3 | GIT_REPOSITORY https://github.com/tristanlabelle/swift-dotnetmetadata.git 4 | GIT_TAG 606bf2b2be7f4cc1d82e4512517f0099bb1c27e3 5 | SOURCE_SUBDIR "don't use cmakelists") 6 | FetchContent_MakeAvailable(swift-dotnetmetadata) 7 | 8 | add_subdirectory("${swift-dotnetmetadata_SOURCE_DIR}/Sources" "${CMAKE_CURRENT_BINARY_DIR}/Sources") 9 | set(WINMDCORLIB_DIR "${swift-dotnetmetadata_SOURCE_DIR}/WindowsMetadataCoreLibrary" PARENT_SCOPE) -------------------------------------------------------------------------------- /Generator/NuGet/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if("${PACKAGE_VERSION}" STREQUAL "") 2 | set(PACKAGE_VERSION "0.0.0") 3 | endif() 4 | set(PACKAGE_FILENAME "TristanLabelle.SwiftWinRT.${PACKAGE_VERSION}.nupkg") 5 | 6 | if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AMD64") 7 | set(EXE_SWITCH "-X64Exe") 8 | else() 9 | set(EXE_SWITCH "-Arm64Exe") 10 | endif() 11 | 12 | add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_FILENAME}" 13 | COMMAND powershell.exe -File "${CMAKE_CURRENT_SOURCE_DIR}/Create-Package.ps1" 14 | "${EXE_SWITCH}" "$" 15 | -MscorlibWinMD "${CMAKE_CURRENT_BINARY_DIR}/../mscorlib.winmd" 16 | -Version "${PACKAGE_VERSION}" 17 | -IntermediateDir "${CMAKE_CURRENT_BINARY_DIR}" 18 | -OutputPath "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_FILENAME}" 19 | DEPENDS 20 | "${CMAKE_CURRENT_SOURCE_DIR}/Create-Package.ps1" 21 | SwiftWinRT 22 | "${CMAKE_CURRENT_BINARY_DIR}/../mscorlib.winmd") 23 | 24 | add_custom_target(NuGetPackage 25 | DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_FILENAME}") -------------------------------------------------------------------------------- /Generator/NuGet/Package.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TristanLabelle.SwiftWinRT 5 | 0.0.0.1 6 | Swift/WinRT 7 | Tristan Labelle 8 | false 9 | A Swift projection for WinRT APIs, written in pure Swift, for consuming modern Windows Runtime APIs, the Windows App SDK, WinUI and arbitrary WinRT components. 10 | Swift WinRT 11 | © Tristan Labelle. All rights reserved. 12 | https://github.com/tristanlabelle/swift-winrt 13 | 14 | MIT 15 | Readme.md 16 | 17 | -------------------------------------------------------------------------------- /Generator/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "swift-argument-parser", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/apple/swift-argument-parser", 7 | "state" : { 8 | "revision" : "8f4d2753f0e4778c76d5f05ad16c74f707390531", 9 | "version" : "1.2.3" 10 | } 11 | }, 12 | { 13 | "identity" : "swift-collections", 14 | "kind" : "remoteSourceControl", 15 | "location" : "https://github.com/apple/swift-collections", 16 | "state" : { 17 | "revision" : "d029d9d39c87bed85b1c50adee7c41795261a192", 18 | "version" : "1.0.6" 19 | } 20 | }, 21 | { 22 | "identity" : "swift-dotnetmetadata", 23 | "kind" : "remoteSourceControl", 24 | "location" : "https://github.com/tristanlabelle/swift-dotnetmetadata", 25 | "state" : { 26 | "branch" : "main", 27 | "revision" : "606bf2b2be7f4cc1d82e4512517f0099bb1c27e3" 28 | } 29 | } 30 | ], 31 | "version" : 2 32 | } -------------------------------------------------------------------------------- /Generator/SPMPostBuild.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Builds mscorlib.winmd and locates it next to SwiftWinRT.exe. 4 | 5 | .PARAMETER Config 6 | The build configuration that was used to build SwiftWinRT.exe. 7 | #> 8 | [CmdletBinding(PositionalBinding = $false)] 9 | param( 10 | [Parameter(Mandatory = $true)] 11 | [string] $Config 12 | ) 13 | 14 | $TargetTripleArch = switch ($Env:PROCESSOR_ARCHITECTURE) { 15 | "amd64" { "x86_64" } 16 | "arm64" { "aarch64" } 17 | "x86" { "i686" } 18 | default { throw "Unsupported architecture: $Env:PROCESSOR_ARCHITECTURE" } 19 | } 20 | 21 | $BinaryDir = "$PSScriptRoot\.build\$TargetTripleArch-unknown-windows-msvc\$Config" 22 | if (-not (Test-Path $BinaryDir)) { 23 | throw "The binary directory does not exist: $BinaryDir" 24 | } 25 | 26 | & "$PSScriptRoot\.build\checkouts\swift-dotnetmetadata\WindowsMetadataCoreLibrary\Assemble.ps1" -OutputPath "$BinaryDir\mscorlib.winmd" -------------------------------------------------------------------------------- /Generator/Sources/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(CodeWriters) 2 | add_subdirectory(ProjectionModel) 3 | add_subdirectory(SwiftWinRT) -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/C/CCallingConvention.swift: -------------------------------------------------------------------------------- 1 | public enum CCallingConvention { 2 | case cdecl 3 | case stdcall 4 | } 5 | 6 | extension CCallingConvention { 7 | public var keyword: String { 8 | switch self { 9 | case .cdecl: return "__cdecl" 10 | case .stdcall: return "__stdcall" 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/C/CEnumerant.swift: -------------------------------------------------------------------------------- 1 | public struct CEnumerant { 2 | public var name: String 3 | public var value: Int? 4 | 5 | public init(name: String, value: Int? = nil) { 6 | self.name = name 7 | self.value = value 8 | } 9 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/C/CParamDecl.swift: -------------------------------------------------------------------------------- 1 | public struct CParamDecl { 2 | public var type: CType 3 | public var name: String? 4 | 5 | public init(type: CType, name: String?) { 6 | self.type = type 7 | self.name = name 8 | } 9 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/C/CType.swift: -------------------------------------------------------------------------------- 1 | public enum CTypeSpecifier { 2 | case reference(kind: CTypeDeclKind? = nil, name: String) 3 | indirect case pointer(to: CType, nullability: CNullability? = nil) 4 | indirect case functionPointer(return: CType, callingConvention: CCallingConvention? = nil, params: [CParamDecl] = []) 5 | } 6 | 7 | public enum CNullability { 8 | case nonnull 9 | case nullable 10 | case unspecified 11 | } 12 | 13 | public struct CType { 14 | public var specifier: CTypeSpecifier 15 | public var const: Bool = false 16 | public var volatile: Bool = false 17 | 18 | public init(_ specifier: CTypeSpecifier, const: Bool = false, volatile: Bool = false) { 19 | self.specifier = specifier 20 | self.const = const 21 | self.volatile = volatile 22 | } 23 | } 24 | 25 | extension CType { 26 | public static func reference(kind: CTypeDeclKind? = nil, name: String, const: Bool = false, volatile: Bool = false) -> Self { 27 | .init(.reference(kind: kind, name: name), const: const, volatile: volatile) 28 | } 29 | 30 | public static func pointer(to pointee: CType, const: Bool = false, volatile: Bool = false, nullability: CNullability? = nil) -> Self { 31 | .init(.pointer(to: pointee, nullability: nullability), const: const, volatile: volatile) 32 | } 33 | 34 | public static let void: Self = .reference(name: "void") 35 | 36 | public func makePointer(const: Bool = false, volatile: Bool = false, nullability: CNullability? = nil) -> Self { 37 | .init(.pointer(to: self, nullability: nullability), const: const, volatile: volatile) 38 | } 39 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/C/CTypeDeclKind.swift: -------------------------------------------------------------------------------- 1 | public enum CTypeDeclKind: Hashable { 2 | case `struct` 3 | case `enum` 4 | case union 5 | } 6 | 7 | extension CTypeDeclKind { 8 | public var keyword: String { 9 | switch self { 10 | case .struct: return "struct" 11 | case .enum: return "enum" 12 | case .union: return "union" 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/C/CVariableDecl.swift: -------------------------------------------------------------------------------- 1 | public struct CVariableDecl { 2 | public var type: CType 3 | public var name: String 4 | 5 | public init(type: CType, name: String) { 6 | self.type = type 7 | self.name = name 8 | } 9 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/CMake/CMakeCommandArgument.swift: -------------------------------------------------------------------------------- 1 | public struct CMakeCommandArgument: ExpressibleByStringLiteral { 2 | public let value: String 3 | public let quoted: Bool 4 | 5 | public init(_ value: String, quoted: Bool) { 6 | self.value = value 7 | self.quoted = quoted 8 | } 9 | 10 | public init(autoquote value: String) { 11 | assert(!value.contains("${")) 12 | self.init(value, quoted: value.contains(" ") || value.contains(";")) 13 | } 14 | 15 | public init(stringLiteral value: String) { 16 | self.init(autoquote: value) 17 | } 18 | 19 | public func write(to stream: inout some TextOutputStream) { 20 | if quoted { stream.write("\"") } 21 | stream.write(value.replacingOccurrences(of: "\\", with: "\\\\")) 22 | if quoted { stream.write("\"") } 23 | } 24 | 25 | public static func autoquote(_ value: String) -> CMakeCommandArgument { 26 | Self(autoquote: value) 27 | } 28 | 29 | public static func quoted(_ value: String) -> CMakeCommandArgument { 30 | Self(value, quoted: true) 31 | } 32 | 33 | public static func unquoted(_ value: String) -> CMakeCommandArgument { 34 | Self(value, quoted: false) 35 | } 36 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/CMake/CMakeLibraryType.swift: -------------------------------------------------------------------------------- 1 | public enum CMakeLibraryType: String { 2 | case `static` = "STATIC" 3 | case shared = "SHARED" 4 | case interface = "INTERFACE" 5 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/CMake/CMakeVisibility.swift: -------------------------------------------------------------------------------- 1 | public enum CMakeVisibility: String { 2 | case `public` = "PUBLIC" 3 | case `private` = "PRIVATE" 4 | case `interface` = "INTERFACE" 5 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SOURCES *.swift) 2 | add_library(CodeWriters STATIC ${SOURCES}) -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/FileTextOutputStream.swift: -------------------------------------------------------------------------------- 1 | import class Foundation.FileManager 2 | 3 | public class FileTextOutputStream: TextOutputStream { 4 | public enum DirectoryCreation { 5 | case none 6 | case parent 7 | case ancestors 8 | } 9 | 10 | public let path: String 11 | private let writeAtomically: Bool 12 | private let directoryCreation: DirectoryCreation 13 | public var text: String = String() 14 | 15 | public init(path: String, writeAtomically: Bool = false, directoryCreation: DirectoryCreation = .none) { 16 | self.path = path 17 | self.writeAtomically = writeAtomically 18 | self.directoryCreation = directoryCreation 19 | } 20 | 21 | public func write(_ string: String) { 22 | text.write(string) 23 | } 24 | 25 | deinit { 26 | do { 27 | if directoryCreation != .none, let lastDirectorySeparatorIndex = path.lastIndex(of: "\\") { 28 | let directoryPath = String(path[.. Block { .paragraph([span]) } 14 | public static func paragraph(_ text: String) -> Block { .paragraph(.text(text)) } 15 | 16 | public struct ListItem: Hashable { 17 | public var text: [Span] 18 | 19 | public init(text: [Span]) { 20 | self.text = text 21 | } 22 | } 23 | } 24 | 25 | public enum Span: Hashable { 26 | case text(String) 27 | case code(String) 28 | } 29 | 30 | public struct Param { 31 | public var name: String 32 | public var description: [Span] 33 | 34 | public init(name: String, description: [Span]) { 35 | self.name = name 36 | self.description = description 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/Swift/SwiftImportKind.swift: -------------------------------------------------------------------------------- 1 | public enum SwiftImportKind: Hashable { 2 | case `typealias` 3 | case `struct` 4 | case `class` 5 | case `enum` 6 | case `protocol` 7 | case `let` 8 | case `var` 9 | case `func` 10 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/Swift/SwiftOperatorLocation.swift: -------------------------------------------------------------------------------- 1 | public enum SwiftOperatorLocation { 2 | case prefix 3 | case infix 4 | case postfix 5 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/Swift/SwiftParameter.swift: -------------------------------------------------------------------------------- 1 | public struct SwiftParam: CustomStringConvertible, TextOutputStreamable { 2 | public var label: SwiftIdentifier? 3 | public var name: SwiftIdentifier 4 | public var `inout`: Bool 5 | public var consuming: Bool 6 | public var escaping: Bool 7 | public var type: SwiftType 8 | public var defaultValue: String? 9 | 10 | public init(label: String? = nil, name: String, `inout`: Bool = false, consuming: Bool = false, escaping: Bool = false, type: SwiftType, defaultValue: String? = nil) { 11 | self.label = label.map { SwiftIdentifier($0) } 12 | self.name = SwiftIdentifier(name) 13 | self.inout = `inout` 14 | self.consuming = consuming 15 | self.escaping = escaping 16 | self.type = type 17 | self.defaultValue = defaultValue 18 | } 19 | 20 | public var description: String { 21 | var output = "" 22 | write(to: &output) 23 | return output 24 | } 25 | 26 | public func write(to output: inout some TextOutputStream) { 27 | if let label { 28 | label.write(to: &output) 29 | output.write(" ") 30 | } 31 | 32 | name.write(to: &output) 33 | output.write(": ") 34 | if `inout` { output.write("inout ") } 35 | if consuming { output.write("consuming ") } 36 | if escaping { output.write("@escaping ") } 37 | type.write(to: &output) 38 | if let defaultValue { 39 | output.write(" = ") 40 | output.write(defaultValue) 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/Swift/SwiftVisibility.swift: -------------------------------------------------------------------------------- 1 | public enum SwiftVisibility { 2 | case implicit 3 | case `internal` 4 | case `private` 5 | case `fileprivate` 6 | case `public` 7 | case `open` 8 | } 9 | 10 | extension SwiftVisibility: CustomStringConvertible, TextOutputStreamable { 11 | public var description: String { 12 | var result = "" 13 | write(to: &result, trailingSpace: false) 14 | return result 15 | } 16 | 17 | public func write(to output: inout some TextOutputStream) { 18 | write(to: &output, trailingSpace: false) 19 | } 20 | 21 | public func write(to output: inout some TextOutputStream, trailingSpace: Bool) { 22 | switch self { 23 | case .implicit: return 24 | case .internal: output.write("internal") 25 | case .private: output.write("private") 26 | case .fileprivate: output.write("fileprivate") 27 | case .public: output.write("public") 28 | case .open: output.write("open") 29 | } 30 | 31 | if trailingSpace { output.write(" ") } 32 | } 33 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/Swift/SyntaxWriters/DocumentationComments.swift: -------------------------------------------------------------------------------- 1 | 2 | extension SwiftSyntaxWriter { 3 | internal func writeDocumentationComment(_ documentationComment: SwiftDocumentationComment) { 4 | output.writeLineBlock(group: .alone, prefix: "/// ") { 5 | if let summary = documentationComment.summary { 6 | for block in summary { writeDocumentationCommentBlock(block) } 7 | } 8 | 9 | for param in documentationComment.params { 10 | output.write("- Parameter ") 11 | output.write(param.name) 12 | output.write(": ") 13 | for span in param.description { writeDocumentationCommentSpan(span) } 14 | output.endLine(groupWithNext: true) 15 | } 16 | 17 | if let returns = documentationComment.returns { 18 | output.write("- Returns: ") 19 | for span in returns { writeDocumentationCommentSpan(span) } 20 | output.endLine(groupWithNext: true) 21 | } 22 | } 23 | output.endLine(groupWithNext: true) 24 | } 25 | 26 | fileprivate func writeDocumentationCommentBlock(_ block: SwiftDocumentationComment.Block) { 27 | switch block { 28 | case .paragraph(let spans): 29 | for span in spans { writeDocumentationCommentSpan(span) } 30 | output.endLine(groupWithNext: true) 31 | default: 32 | return // TODO: Support more block types 33 | } 34 | } 35 | 36 | fileprivate func writeDocumentationCommentSpan(_ span: SwiftDocumentationComment.Span) { 37 | switch span { 38 | case .text(let string): output.write(string) 39 | default: 40 | return // TODO: Support more inline types 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Generator/Sources/CodeWriters/Swift/SyntaxWriters/SourceFile.swift: -------------------------------------------------------------------------------- 1 | public struct SwiftSourceFileWriter: SwiftDeclarationWriter { 2 | public let output: LineBasedTextOutputStream 3 | 4 | public init(output: some TextOutputStream, indent: String = " ") { 5 | self.output = LineBasedTextOutputStream(inner: output, defaultBlockLinePrefix: indent) 6 | } 7 | 8 | public func writeImport(exported: Bool = false, module: String) { 9 | output.beginLine(group: .named("import")) 10 | if exported { output.write("@_exported ") } 11 | output.write("import ") 12 | output.write(module, endLine: true) 13 | } 14 | 15 | public func writeImport(exported: Bool = false, kind: SwiftImportKind, module: String, symbolName: String) { 16 | output.beginLine(group: .named("import")) 17 | if exported { output.write("@_exported ") } 18 | output.write("import ") 19 | output.write(String(describing: kind)) 20 | output.write(" ") 21 | output.write(module) 22 | output.write(".") 23 | output.write(symbolName, endLine: true) 24 | } 25 | 26 | public func writeExtension( 27 | attributes: [SwiftAttribute] = [], 28 | type: SwiftType, 29 | protocolConformances: [SwiftType] = [], 30 | whereClauses: [String] = [], 31 | members: (SwiftTypeDefinitionWriter) throws -> Void) rethrows { 32 | 33 | var output = output 34 | output.beginLine(group: .alone) 35 | writeAttributes(attributes) 36 | output.write("extension ") 37 | type.write(to: &output) 38 | writeInheritanceClause(protocolConformances) 39 | if !whereClauses.isEmpty { 40 | output.write(" where ") 41 | output.write(whereClauses.joined(separator: ", ")) 42 | } 43 | try output.writeBracedIndentedBlock() { 44 | try members(.init(output: output)) 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /Generator/Sources/ProjectionModel/ABIMethodKind.swift: -------------------------------------------------------------------------------- 1 | import DotNetMetadata 2 | import WindowsMetadata 3 | 4 | public enum ABIMethodKind: Equatable { 5 | case normal 6 | case activationFactory 7 | case composableFactory 8 | 9 | public static func forInterfaceMethods(definition: InterfaceDefinition) throws -> ABIMethodKind { 10 | guard let classDefinition = try definition.findAttribute(ExclusiveToAttribute.self)?.target else { 11 | return .normal 12 | } 13 | 14 | for activatableAttribute in try classDefinition.getAttributes(ActivatableAttribute.self) { 15 | if activatableAttribute.factory == definition { 16 | return .activationFactory 17 | } 18 | } 19 | 20 | for composableAttribute in try classDefinition.getAttributes(ComposableAttribute.self) { 21 | if composableAttribute.factory == definition { 22 | return .composableFactory 23 | } 24 | } 25 | 26 | return .normal 27 | } 28 | 29 | public static func forABITypeMethods(definition: TypeDefinition) throws -> ABIMethodKind { 30 | guard let interfaceDefinition = definition as? InterfaceDefinition else { 31 | return .normal 32 | } 33 | return try forInterfaceMethods(definition: interfaceDefinition) 34 | } 35 | } -------------------------------------------------------------------------------- /Generator/Sources/ProjectionModel/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SOURCES *.swift) 2 | add_library(ProjectionModel STATIC ${SOURCES}) 3 | target_link_libraries(ProjectionModel PUBLIC 4 | Collections 5 | CodeWriters 6 | DotNetMetadata 7 | DotNetMetadataFormat 8 | DotNetXMLDocs 9 | DotNetXMLDocsFromMetadata 10 | WindowsMetadata) -------------------------------------------------------------------------------- /Generator/Sources/ProjectionModel/Casing.swift: -------------------------------------------------------------------------------- 1 | public enum Casing { 2 | public static func pascalToCamel(_ str: String) -> String { 3 | // "" -> "" 4 | // fooBar -> fooBar 5 | guard str.first?.isUppercase == true else { return str } 6 | var lastUpperCaseIndex = str.startIndex 7 | while true { 8 | let nextIndex = str.index(after: lastUpperCaseIndex) 9 | guard nextIndex < str.endIndex else { break } 10 | guard str[nextIndex].isUppercase else { break } 11 | lastUpperCaseIndex = nextIndex 12 | } 13 | 14 | let firstNonUpperCaseIndex = str.index(after: lastUpperCaseIndex) 15 | 16 | // FOOBAR -> foobar 17 | if firstNonUpperCaseIndex == str.endIndex { 18 | return str.lowercased() 19 | } 20 | 21 | // FooBar -> fooBar 22 | if lastUpperCaseIndex == str.startIndex { 23 | return str[lastUpperCaseIndex].lowercased() + str[firstNonUpperCaseIndex...] 24 | } 25 | 26 | // UIElement -> uiElement 27 | return str[...lastUpperCaseIndex].lowercased() + str[firstNonUpperCaseIndex...] 28 | } 29 | } -------------------------------------------------------------------------------- /Generator/Sources/ProjectionModel/ClassFactoryKind.swift: -------------------------------------------------------------------------------- 1 | public enum ClassFactoryKind { 2 | case activatable 3 | case composable 4 | } -------------------------------------------------------------------------------- /Generator/Sources/ProjectionModel/Projection+abi.swift: -------------------------------------------------------------------------------- 1 | import CodeWriters 2 | import DotNetMetadata 3 | import WindowsMetadata 4 | 5 | extension Projection { 6 | public func toABIType(_ type: BoundType) throws -> SwiftType { 7 | if let classDefinition = type.definition as? ClassDefinition { 8 | // The ABI representation of a (non-static) class is that of its default interface. 9 | precondition(!classDefinition.isStatic) 10 | guard let defaultInterface = try DefaultAttribute.getDefaultInterface(classDefinition) else { 11 | throw WinMDError.missingAttribute 12 | } 13 | return try toABIType(defaultInterface.asBoundType) 14 | } 15 | 16 | return .named(try CAbi.mangleName(type: type)) 17 | } 18 | 19 | public func toABIVirtualTableType(_ type: BoundType) throws -> SwiftType { 20 | precondition(type.definition is InterfaceDefinition || type.definition is DelegateDefinition) 21 | return .named(try CAbi.mangleName(type: type) + CAbi.virtualTableSuffix) 22 | } 23 | } -------------------------------------------------------------------------------- /Generator/Sources/ProjectionModel/Projection.swift: -------------------------------------------------------------------------------- 1 | import Collections 2 | import DotNetMetadata 3 | import DotNetXMLDocs 4 | 5 | /// Describes how to project a collection of Windows metadata assemblies into Swift modules. 6 | public class Projection { 7 | internal struct AssemblyEntry { 8 | var module: Module 9 | var documentation: AssemblyDocumentation? 10 | } 11 | 12 | public private(set) var modulesByName = OrderedDictionary() 13 | internal var assembliesToModules = [Assembly: AssemblyEntry]() 14 | public let deprecations: Bool 15 | 16 | public init(deprecations: Bool = true) { 17 | self.deprecations = deprecations 18 | } 19 | 20 | public func addModule(name: String) -> Module { 21 | precondition(modulesByName[name] == nil) 22 | let module = Module(projection: self, name: name) 23 | modulesByName[name] = module 24 | modulesByName.sort { $0.key < $1.key } 25 | return module 26 | } 27 | 28 | public func getModule(_ assembly: Assembly) -> Module? { 29 | assembliesToModules[assembly]?.module 30 | } 31 | 32 | internal func addAssembly(_ assembly: Assembly, module: Module, documentation: AssemblyDocumentation? = nil) { 33 | assembliesToModules[assembly] = AssemblyEntry(module: module, documentation: documentation) 34 | } 35 | } -------------------------------------------------------------------------------- /Generator/Sources/ProjectionModel/String+prefixes.swift: -------------------------------------------------------------------------------- 1 | extension String { 2 | func findPrefixEndIndex(_ prefix: String) -> String.Index? { 3 | var prefixIndex = prefix.startIndex 4 | var selfIndex = self.startIndex 5 | while prefixIndex != prefix.endIndex { 6 | guard selfIndex != self.endIndex, self[selfIndex] == prefix[prefixIndex] else { return nil } 7 | prefixIndex = prefix.index(after: prefixIndex) 8 | selfIndex = self.index(after: selfIndex) 9 | } 10 | 11 | return selfIndex 12 | } 13 | } -------------------------------------------------------------------------------- /Generator/Sources/ProjectionModel/Unowned.swift: -------------------------------------------------------------------------------- 1 | /// A wrapper around an unowned reference to an object. 2 | internal struct Unowned: Hashable where Object: AnyObject { 3 | unowned var object: Object 4 | 5 | public init(_ object: Object) { 6 | self.object = object 7 | } 8 | 9 | public func hash(into hasher: inout Hasher) { 10 | hasher.combine(ObjectIdentifier(object)) 11 | } 12 | 13 | public static func == (lhs: Self, rhs: Self) -> Bool { 14 | lhs.object === rhs.object 15 | } 16 | } -------------------------------------------------------------------------------- /Generator/Sources/ProjectionModel/WinRTMethodKind.swift: -------------------------------------------------------------------------------- 1 | import DotNetMetadata 2 | 3 | public enum WinRTMethodKind { 4 | case regular 5 | case constructor 6 | case propertyGetter 7 | case propertySetter 8 | case eventAdder 9 | case eventRemover 10 | case delegateInvoke 11 | 12 | // No finalizers, no static constructors, no misc property/event accessors, no indexers, no operator overloads 13 | public init(from method: Method) { 14 | if method.name.starts(with: "get_") { self = .propertyGetter } 15 | else if method.name.starts(with: "set_") { self = .propertySetter } 16 | else if method.name.starts(with: "add_") { self = .eventAdder } 17 | else if method.name.starts(with: "remove_") { self = .eventRemover } 18 | else if method.name == ".ctor" { self = .constructor } 19 | else if method.name == "Invoke" && method.definingType is DelegateDefinition { self = .delegateInvoke } 20 | else { self = .regular } 21 | } 22 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(Extensions) 2 | 3 | file(GLOB_RECURSE SOURCES *.swift) 4 | add_executable(SwiftWinRT ${SOURCES}) 5 | target_sources(SwiftWinRT PRIVATE "${PACKAGERESOURCES_SWIFT_FILE}") 6 | target_link_libraries(SwiftWinRT PRIVATE 7 | ArgumentParser Collections 8 | DotNetMetadata DotNetMetadataFormat WindowsMetadata 9 | CodeWriters ProjectionModel) 10 | 11 | if(DEFINED GENERATOR_STAGING_DIR) 12 | add_custom_command(TARGET SwiftWinRT POST_BUILD 13 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 14 | "${CMAKE_CURRENT_BINARY_DIR}/SwiftWinRT.exe" 15 | "${GENERATOR_STAGING_DIR}/SwiftWinRT.exe" 16 | BYPRODUCTS "${GENERATOR_STAGING_DIR}/SwiftWinRT.exe") 17 | endif() -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/CMakeOptions.swift: -------------------------------------------------------------------------------- 1 | struct CMakeOptions { 2 | public var dynamicLibraries: Bool 3 | public var moduleTargetNameOverrides: [String: String] 4 | 5 | public func getTargetName(moduleName: String) -> String { 6 | moduleTargetNameOverrides[moduleName] ?? moduleName 7 | } 8 | 9 | public init?(commandLineArguments: CommandLineArguments, projectionConfig: ProjectionConfig) { 10 | guard commandLineArguments.generateCMakeLists else { return nil } 11 | 12 | self.dynamicLibraries = commandLineArguments.dynamicLibraries 13 | 14 | self.moduleTargetNameOverrides = .init() 15 | for (moduleName, moduleConfig) in projectionConfig.modules { 16 | if let targetName = moduleConfig.cmakeTargetName { 17 | self.moduleTargetNameOverrides[moduleName] = targetName 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Extensions/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Build the resource embedding code 2 | set(PACKAGERESOURCES_CODE "enum PackageResources {\n") 3 | file(GLOB RESOURCES "*_swift") 4 | foreach(RESOURCE ${RESOURCES}) 5 | get_filename_component(RESOURCE_NAME ${RESOURCE} NAME) 6 | file(READ ${RESOURCE} RESOURCE_HEX HEX) 7 | string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," RESOURCE_HEX ${RESOURCE_HEX}) 8 | string(APPEND PACKAGERESOURCES_CODE " static let ${RESOURCE_NAME}: [UInt8] = [ ${RESOURCE_HEX} ]\n") 9 | endforeach() 10 | string(APPEND PACKAGERESOURCES_CODE "}\n") 11 | 12 | # Update the file if the code has changed 13 | set(PACKAGERESOURCES_SWIFT_FILE "${CMAKE_CURRENT_BINARY_DIR}/PackageResources.swift") 14 | set(PACKAGERESOURCES_OLD_CODE "") 15 | if(EXISTS "${PACKAGERESOURCES_SWIFT_FILE}") 16 | file(READ "${PACKAGERESOURCES_SWIFT_FILE}" PACKAGERESOURCES_OLD_CODE) 17 | endif() 18 | if(NOT "${PACKAGERESOURCES_CODE}" STREQUAL "${PACKAGERESOURCES_OLD_CODE}") 19 | file(WRITE "${PACKAGERESOURCES_SWIFT_FILE}" "${PACKAGERESOURCES_CODE}") 20 | endif() 21 | 22 | # Return the path 23 | set(PACKAGERESOURCES_SWIFT_FILE "${PACKAGERESOURCES_SWIFT_FILE}" PARENT_SCOPE) 24 | -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Extensions/WindowsFoundationCollections_IIterable_swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime 2 | 3 | extension Sequence { 4 | /// Converts a Swift sequence to a WinRT IIterable. 5 | /// - Parameter sequence: The sequence to convert. 6 | /// - Returns: The converted IIterable. 7 | public func toWinRTIIterable() -> WindowsFoundationCollections_IIterable { 8 | SequenceIterable(self) 9 | } 10 | } 11 | 12 | fileprivate class SequenceIterable: WinRTExportBase, WindowsFoundationCollections_IIterableProtocol { 13 | typealias T = S.Element 14 | 15 | private let sequence: S 16 | 17 | init(_ sequence: S) { 18 | self.sequence = sequence 19 | } 20 | 21 | func first() throws -> WindowsFoundationCollections_IIterator { 22 | SequenceIterator(sequence.makeIterator()) 23 | } 24 | } 25 | 26 | internal class SequenceIterator: WinRTExportBase, WindowsFoundationCollections_IIteratorProtocol { 27 | typealias T = I.Element 28 | 29 | private var iterator: I 30 | private var _current: T? 31 | 32 | init(_ iterator: I) { 33 | self.iterator = iterator 34 | self._current = self.iterator.next() 35 | } 36 | 37 | var hasCurrent: Bool { get throws { _current != nil } } 38 | 39 | var current: T { 40 | get throws { 41 | guard let _current else { throw COMError.illegalMethodCall } 42 | return _current 43 | } 44 | } 45 | 46 | func moveNext() throws -> Bool { 47 | _current = iterator.next() 48 | return _current != nil 49 | } 50 | 51 | func getMany(_ items: [I.Element]) throws -> UInt32 { 52 | throw COMError.notImpl // TODO(#31): Implement out arrays 53 | } 54 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Extensions/WindowsFoundation_IAsyncActionWithProgress_swift: -------------------------------------------------------------------------------- 1 | import COM 2 | import WindowsRuntime 3 | 4 | extension WindowsFoundation_IAsyncActionWithProgressProtocol { 5 | public func get() async throws { 6 | if try self.status == .started { 7 | // We can't await if the completed handler is already set 8 | guard try COM.NullResult.catch(self.completed) == nil else { throw COM.COMError.illegalMethodCall } 9 | let awaiter = WindowsRuntime.AsyncAwaiter() 10 | try self.completed { _, _ in _Concurrency.Task { await awaiter.signal() } } 11 | await awaiter.wait() 12 | } 13 | 14 | return try getResults() 15 | } 16 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Extensions/WindowsFoundation_IAsyncAction_swift: -------------------------------------------------------------------------------- 1 | import COM 2 | import WindowsRuntime 3 | 4 | extension WindowsFoundation_IAsyncActionProtocol { 5 | public func get() async throws { 6 | if try self.status == .started { 7 | // We can't await if the completed handler is already set 8 | guard try COM.NullResult.catch(self.completed) == nil else { throw COM.COMError.illegalMethodCall } 9 | let awaiter = WindowsRuntime.AsyncAwaiter() 10 | try self.completed { _, _ in _Concurrency.Task { await awaiter.signal() } } 11 | await awaiter.wait() 12 | } 13 | 14 | return try getResults() 15 | } 16 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Extensions/WindowsFoundation_IAsyncOperationWithProgress_swift: -------------------------------------------------------------------------------- 1 | import COM 2 | import WindowsRuntime 3 | 4 | extension WindowsFoundation_IAsyncOperationWithProgressProtocol { 5 | public func get() async throws -> TResult { 6 | if try self.status == .started { 7 | // We can't await if the completed handler is already set 8 | guard try COM.NullResult.catch(self.completed) == nil else { throw COM.COMError.illegalMethodCall } 9 | let awaiter = WindowsRuntime.AsyncAwaiter() 10 | try self.completed { _, _ in _Concurrency.Task { await awaiter.signal() } } 11 | await awaiter.wait() 12 | } 13 | 14 | return try getResults() 15 | } 16 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Extensions/WindowsFoundation_IAsyncOperation_swift: -------------------------------------------------------------------------------- 1 | import COM 2 | import WindowsRuntime 3 | 4 | extension WindowsFoundation_IAsyncOperationProtocol { 5 | public func get() async throws -> TResult { 6 | if try self.status == .started { 7 | // We can't await if the completed handler is already set 8 | guard try COM.NullResult.catch(self.completed) == nil else { throw COM.COMError.illegalMethodCall } 9 | let awaiter = WindowsRuntime.AsyncAwaiter() 10 | try self.completed { _, _ in _Concurrency.Task { await awaiter.signal() } } 11 | await awaiter.wait() 12 | } 13 | 14 | return try getResults() 15 | } 16 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Extensions/WindowsFoundation_IMemoryBufferReference_swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime 2 | 3 | extension WindowsFoundation_IMemoryBufferReferenceProtocol { 4 | public var bytes: UnsafeMutableBufferPointer? { 5 | get throws { 6 | let byteAccess = try self._queryInterface(IMemoryBufferByteAccessBinding.self) 7 | return try byteAccess.interop.getBuffer() 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Extensions/WindowsFoundation_IMemoryBuffer_swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime 2 | 3 | extension Array where Element == UInt8 { 4 | public init(_ buffer: WindowsFoundation_IMemoryBuffer) throws { 5 | let reference = try buffer.createReference() 6 | guard let bufferPointer = try reference.bytes else { throw COMError.fail } 7 | self.init(bufferPointer) 8 | } 9 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Extensions/WindowsFoundation_MemoryBuffer_swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime 2 | 3 | extension WindowsFoundation_MemoryBuffer { 4 | public convenience init(_ bytes: [UInt8]) throws { 5 | try self.init(UInt32(bytes.count)) 6 | let reference = try self.createReference() 7 | guard let bufferPointer = try reference.bytes else { throw COMError.fail } 8 | _ = bufferPointer.update(fromContentsOf: bytes) 9 | } 10 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Extensions/WindowsStorageStreams_Buffer_swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime 2 | 3 | extension WindowsStorageStreams_Buffer { 4 | public convenience init(_ bytes: [UInt8]) throws { 5 | try self.init(UInt32(bytes.count)) 6 | try self.length(UInt32(bytes.count)) 7 | let byteAccess = try self._queryInterface(IBufferByteAccessBinding.self) 8 | let bufferPointer = try UnsafeMutableBufferPointer(start: byteAccess.interop.buffer(), count: bytes.count) 9 | _ = bufferPointer.update(fromContentsOf: bytes) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Extensions/WindowsStorageStreams_IBuffer_swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime 2 | 3 | extension WindowsStorageStreams_IBufferProtocol { 4 | public var bytes: UnsafeMutablePointer? { 5 | get throws { 6 | let byteAccess = try self._queryInterface(IBufferByteAccessBinding.self) 7 | return try byteAccess.interop.buffer() 8 | } 9 | } 10 | } 11 | 12 | extension Array where Element == UInt8 { 13 | public init(_ buffer: WindowsStorageStreams_IBuffer) throws { 14 | self.init(try UnsafeBufferPointer(start: buffer.bytes, count: Int(buffer.length))) 15 | } 16 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Filter.swift: -------------------------------------------------------------------------------- 1 | internal enum Filter { 2 | case exact(String) 3 | case regex(Regex) 4 | 5 | public init(pattern: String) { 6 | if pattern.contains("*") { 7 | var regexPattern = "^" 8 | regexPattern += Self.escapeRegexPattern(pattern) 9 | regexPattern.replace("\\*", with: ".*") 10 | regexPattern += "$" 11 | 12 | self = .regex(try! Regex(regexPattern)) 13 | } 14 | else { 15 | self = .exact(pattern) 16 | } 17 | } 18 | 19 | public func matches(_ value: String) -> Bool { 20 | switch self { 21 | case .exact(let filter): return value == filter 22 | case .regex(let regex): return (try? regex.wholeMatch(in: value)) != nil 23 | } 24 | } 25 | 26 | private static func escapeRegexPattern(_ pattern: String) -> String { 27 | var result = "" 28 | for char in pattern { 29 | if "[](){}+*.^$|?".contains(char) { result += "\\" } 30 | result.append(char) 31 | } 32 | return result 33 | } 34 | } 35 | 36 | internal struct FilterSet { 37 | private var filters: [Filter]? 38 | 39 | public init(_ filters: [Filter]?) { 40 | self.filters = filters 41 | } 42 | 43 | public var matchesNothing: Bool { filters?.count == 0 } 44 | 45 | public func matches(_ value: String) -> Bool { 46 | guard let filters else { return true } 47 | return filters.contains { $0.matches(value) } 48 | } 49 | } -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/SPMOptions.swift: -------------------------------------------------------------------------------- 1 | struct SPMOptions { 2 | public var supportPackageReference: String 3 | public var dynamicLibraries: Bool 4 | public var excludeCMakeLists: Bool 5 | public var moduleLibraryNameOverrides: [String: String] 6 | 7 | public func getLibraryName(moduleName: String) -> String { 8 | moduleLibraryNameOverrides[moduleName] ?? moduleName 9 | } 10 | 11 | public init?(commandLineArguments: CommandLineArguments, projectionConfig: ProjectionConfig) { 12 | guard commandLineArguments.generatePackageDotSwift else { return nil } 13 | 14 | self.supportPackageReference = commandLineArguments.spmSupportPackageReference 15 | self.dynamicLibraries = commandLineArguments.dynamicLibraries 16 | self.excludeCMakeLists = !commandLineArguments.generateCMakeLists 17 | 18 | self.moduleLibraryNameOverrides = .init() 19 | for (moduleName, moduleConfig) in projectionConfig.modules { 20 | if let libraryName = moduleConfig.spmLibraryName { 21 | self.moduleLibraryNameOverrides[moduleName] = libraryName 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Generator/Sources/SwiftWinRT/Writing/SourcePreamble.swift: -------------------------------------------------------------------------------- 1 | import CodeWriters 2 | import ProjectionModel 3 | 4 | internal func writeGeneratedCodePreamble(to writer: SwiftSourceFileWriter) { 5 | writer.writeCommentLine("Generated by swift-winrt") 6 | writer.writeCommentLine("swiftlint:disable all", groupWithNext: false) 7 | } 8 | 9 | internal func writeModulePreamble(_ module: Module, importABI: Bool = true, to writer: SwiftSourceFileWriter) { 10 | writer.writeImport(module: SupportModules.WinRT.moduleName) 11 | 12 | if importABI { 13 | writer.writeImport(module: module.abiModuleName) 14 | } 15 | 16 | for referencedModule in module.references { 17 | guard !referencedModule.isEmpty else { continue } 18 | writer.writeImport(module: referencedModule.name) 19 | } 20 | } -------------------------------------------------------------------------------- /Generator/Tests/SwiftSyntaxWriterTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import CodeWriters 3 | 4 | class SwiftSyntaxWriterTests: XCTestCase { 5 | func testNewLineInDocumentationComment() throws { 6 | let writer = SwiftSourceFileWriter(output: "") 7 | 8 | var docs = SwiftDocumentationComment() 9 | docs.summary = [.paragraph(.text("A\nB"))] 10 | writer.writeStoredProperty( 11 | documentation: docs, 12 | declarator: .let, 13 | name: "answer", 14 | initialValue: "42") 15 | 16 | let lines = try XCTUnwrap(writer.output.inner as? String) 17 | .trimmingCharacters(in: .whitespacesAndNewlines) 18 | .split(separator: "\n", omittingEmptySubsequences: false) 19 | .map { String($0) } 20 | XCTAssertEqual(lines, [ 21 | "/// A", 22 | "/// B", 23 | "let answer = 42" 24 | ]) 25 | } 26 | 27 | // Regression test for https://github.com/tristanlabelle/swift-winrt/issues/358 28 | func testDocumentationCommentSpacing() throws { 29 | let writer = SwiftSourceFileWriter(output: "") 30 | 31 | writer.writeStoredProperty(declarator: .let, name: "first", initialValue: "1") 32 | 33 | var docs = SwiftDocumentationComment() 34 | docs.summary = [.paragraph(.text("Docs"))] 35 | writer.writeStoredProperty(documentation: docs, declarator: .let, name: "second", initialValue: "2") 36 | 37 | let lines = try XCTUnwrap(writer.output.inner as? String) 38 | .trimmingCharacters(in: .whitespacesAndNewlines) 39 | .split(separator: "\n", omittingEmptySubsequences: false) 40 | .map { String($0) } 41 | XCTAssertEqual(lines, [ 42 | "let first = 1", 43 | "", 44 | "/// Docs", 45 | "let second = 2" 46 | ]) 47 | } 48 | } -------------------------------------------------------------------------------- /Generator/mscorlib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Assemble DotNetMetadata's mscorlib.il into mscorlib.winmd, 2 | # which is required by the code generator. 3 | add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mscorlib.winmd" 4 | COMMAND powershell.exe -File "${WINMDCORLIB_DIR}/Assemble.ps1" 5 | -SourcePath "${WINMDCORLIB_DIR}/mscorlib.il" 6 | -OutputPath "${CMAKE_CURRENT_BINARY_DIR}/mscorlib.winmd" 7 | DEPENDS 8 | "${WINMDCORLIB_DIR}/Assemble.ps1" 9 | "${WINMDCORLIB_DIR}/mscorlib.il") 10 | 11 | add_custom_target(mscorlib ALL 12 | DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/mscorlib.winmd") 13 | 14 | if(DEFINED GENERATOR_STAGING_DIR) 15 | add_custom_command(TARGET mscorlib POST_BUILD 16 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 17 | "${CMAKE_CURRENT_BINARY_DIR}/mscorlib.winmd" 18 | "${GENERATOR_STAGING_DIR}/mscorlib.winmd" 19 | BYPRODUCTS "${GENERATOR_STAGING_DIR}/mscorlib.winmd") 20 | endif() -------------------------------------------------------------------------------- /InteropTests/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "swift", 6 | "args": [ 7 | "build", 8 | "--build-tests", 9 | "-Xlinker", 10 | "-debug:dwarf" 11 | ], 12 | "disableTaskQueue": true, 13 | "problemMatcher": [ 14 | "$swiftc" 15 | ], 16 | "group": { 17 | "kind": "build", 18 | "isDefault": true 19 | }, 20 | "label": "swift: Build All", 21 | "detail": "swift build --build-tests -Xlinker -debug:dwarf" 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /InteropTests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Support using this directory as a standalone project or as a subdirectory. 2 | if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") 3 | cmake_minimum_required(VERSION 3.21.0) 4 | project(InteropTests LANGUAGES C Swift) 5 | endif() 6 | 7 | if (NOT DEFINED SWIFTWINRT_EXE) 8 | message(FATAL_ERROR "SWIFTWINRT_EXE must be defined") 9 | endif() 10 | cmake_path(ABSOLUTE_PATH SWIFTWINRT_EXE NORMALIZE) 11 | 12 | # Build the support module if not already the case (by root CMakeLists.txt) 13 | if(NOT TARGET WindowsRuntime) 14 | execute_process( 15 | COMMAND git.exe -C "${CMAKE_CURRENT_SOURCE_DIR}" rev-parse --path-format=absolute --show-toplevel 16 | OUTPUT_VARIABLE REPO_ROOT 17 | OUTPUT_STRIP_TRAILING_WHITESPACE 18 | COMMAND_ERROR_IS_FATAL ANY) 19 | add_subdirectory("${REPO_ROOT}/Support/Sources" "${CMAKE_CURRENT_BINARY_DIR}/Support") 20 | endif() 21 | 22 | add_subdirectory(WinRTComponent) 23 | -------------------------------------------------------------------------------- /InteropTests/CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 21, 6 | "patch": 0 7 | }, 8 | "configurePresets": [ 9 | { 10 | "name": "debug", 11 | "displayName": "Debug", 12 | "generator": "Ninja", 13 | "binaryDir": "${sourceDir}/build/debug", 14 | "cacheVariables": { 15 | "CMAKE_BUILD_TYPE": "Debug", 16 | "CMAKE_C_COMPILER": "clang", 17 | "CMAKE_C_FLAGS_DEBUG": "-O0 -gdwarf -DNDEBUG", 18 | "CMAKE_Swift_FLAGS_DEBUG": "-DDEBUG -Onone -Xfrontend -g -Xfrontend -debug-info-format=dwarf -use-ld=lld -Xlinker -debug:dwarf" 19 | } 20 | } 21 | ], 22 | "buildPresets": [ 23 | { 24 | "name": "debug", 25 | "displayName": "Debug", 26 | "configurePreset": "debug" 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /InteropTests/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.10 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "InteropTests", 6 | dependencies: [ 7 | .package(name: "Support", path: ".."), 8 | .package(name: "Projection", path: "WinRTComponent/Projection"), 9 | ], 10 | targets: [ 11 | .testTarget( 12 | name: "Tests", 13 | dependencies: [ 14 | .product(name: "WindowsRuntime", package: "Support"), 15 | .product(name: "SwiftUWP", package: "Projection"), 16 | .product(name: "SwiftWinRTComponent", package: "Projection"), 17 | ], 18 | path: "Tests", 19 | linkerSettings: [ .unsafeFlags([ 20 | // Embed the WinRT component manifest to locate activation factories 21 | "-Xlinker", "/manifestinput:WinRTComponent/Projection/WinRTComponent.manifest", 22 | "-Xlinker", "/manifest:embed", 23 | // Workaround for SPM library support limitations causing "LNK4217: locally defined symbol imported" spew 24 | "-Xlinker", "-ignore:4217" 25 | ]) ]) 26 | ] 27 | ) 28 | -------------------------------------------------------------------------------- /InteropTests/Tests/ActivationFactoryResolutionTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import WindowsRuntime 3 | import WinRTComponent 4 | 5 | class ActivationFactoryResolutionTests: WinRTTestCase { 6 | func testCustomResolver() throws { 7 | class Resolver: ActivationFactoryResolver { 8 | private let dllResolver = DllActivationFactoryResolver(name: "WinRTComponent.dll") 9 | var lastRuntimeClass: String? = nil 10 | 11 | func resolve(runtimeClass: String) throws -> COMReference { 12 | lastRuntimeClass = runtimeClass 13 | return try dllResolver.resolve(runtimeClass: runtimeClass) 14 | } 15 | } 16 | 17 | // Temporarily install the new resolver (avoid affecting other tests) 18 | let resolver = Resolver() 19 | let originalResolver = WindowsRuntime.activationFactoryResolver 20 | WindowsRuntime.activationFactoryResolver = resolver 21 | defer { WindowsRuntime.activationFactoryResolver = originalResolver } 22 | 23 | // Trigger the activation factory resolution 24 | try WinRTComponent_ForCustomActivationFactoryResolution.method() 25 | 26 | // Verify that the custom resolver was called 27 | XCTAssertEqual(resolver.lastRuntimeClass, "WinRTComponent.ForCustomActivationFactoryResolution") 28 | } 29 | } -------------------------------------------------------------------------------- /InteropTests/Tests/ActivationFactoryTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import COM 3 | import WindowsRuntime 4 | import WinRTComponent 5 | 6 | class ActivationFactoryTests: WinRTTestCase { 7 | func testDefault() throws { 8 | XCTAssertEqual(try WinRTComponent_OverloadedSum().result, 0) 9 | } 10 | 11 | func testParameterized() throws { 12 | XCTAssertEqual(try WinRTComponent_OverloadedSum(1).result, 1) 13 | XCTAssertEqual(try WinRTComponent_OverloadedSum(1, 2).result, 3) 14 | } 15 | } -------------------------------------------------------------------------------- /InteropTests/Tests/ArrayTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import WinRTComponent 3 | 4 | class ArrayTests: WinRTTestCase { 5 | func testInput() throws { 6 | XCTAssertEqual(try WinRTComponent_Arrays.getLast(["a", "b"]), "b") 7 | } 8 | 9 | func testReturn() throws { 10 | XCTAssertEqual(try WinRTComponent_Arrays.make("a", "b"), ["a", "b"]) 11 | } 12 | 13 | func testOutParam() throws { 14 | var array = [String]() 15 | try WinRTComponent_Arrays.output("a", "b", &array) 16 | XCTAssertEqual(array, ["a", "b"]) 17 | } 18 | 19 | func testByRef() throws { 20 | throw XCTSkip("Not implemented: byref arrays") 21 | } 22 | } -------------------------------------------------------------------------------- /InteropTests/Tests/Asserts.swift: -------------------------------------------------------------------------------- 1 | import COM 2 | import XCTest 3 | 4 | internal func assertCOMIdentical(_ lhs: IUnknown, _ rhs: IUnknown, file: StaticString = #file, line: UInt = #line) { 5 | do { 6 | let lhsReference = try lhs._queryInterface(IUnknownBinding.self) 7 | let rhsReference = try rhs._queryInterface(IUnknownBinding.self) 8 | XCTAssertEqual(lhsReference.pointer, rhsReference.pointer, file: file, line: line) 9 | } 10 | catch { 11 | XCTFail("Failed to query IUnknown from objects: \(error)", file: file, line: line) 12 | } 13 | } -------------------------------------------------------------------------------- /InteropTests/Tests/BuiltInConformancesTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import WinRTComponent 3 | 4 | class BuiltInConformancesTests: WinRTTestCase { 5 | func testCodable() throws { 6 | func isCodable(type: T.Type) -> Bool { T.self is any Decodable.Type && T.self is any Codable.Type } 7 | 8 | XCTAssertTrue(isCodable(type: WinRTComponent_MinimalEnum.self)) 9 | XCTAssertTrue(isCodable(type: WinRTComponent_MinimalStruct.self)) 10 | XCTAssertFalse(isCodable(type: WinRTComponent_MinimalClass.self)) 11 | XCTAssertFalse(isCodable(type: WinRTComponent_MinimalDelegate.self)) 12 | } 13 | 14 | func testHashable() throws { 15 | func isHashable(type: T.Type) -> Bool { T.self is any Hashable.Type } 16 | 17 | XCTAssertTrue(isHashable(type: WinRTComponent_MinimalEnum.self)) 18 | XCTAssertTrue(isHashable(type: WinRTComponent_MinimalStruct.self)) 19 | XCTAssertFalse(isHashable(type: WinRTComponent_MinimalClass.self)) 20 | XCTAssertFalse(isHashable(type: WinRTComponent_MinimalDelegate.self)) 21 | } 22 | 23 | func testSendable() throws { 24 | let minimalEnum: WinRTComponent_MinimalEnum = .init() 25 | let minimalStruct: WinRTComponent_MinimalStruct = .init() 26 | Task { 27 | // Should compile if they are Sendable 28 | let _ = minimalEnum 29 | let _ = minimalStruct 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /InteropTests/Tests/ByteBufferTests.swift: -------------------------------------------------------------------------------- 1 | import UWP 2 | import WindowsRuntime 3 | import WinRTComponent 4 | import XCTest 5 | 6 | class ByteBufferTests : XCTestCase { 7 | public func testConsumeMemoryBuffer() throws { 8 | let bytes: [UInt8] = [1, 2, 3] 9 | let roundtrippedBytes = try Array(WinRTComponent_ByteBuffers.arrayToMemoryBuffer(bytes)) 10 | XCTAssertEqual(roundtrippedBytes, bytes) 11 | } 12 | 13 | public func testConsumeStorageBuffer() throws { 14 | let bytes: [UInt8] = [1, 2, 3] 15 | let roundtrippedBytes = try Array(WinRTComponent_ByteBuffers.arrayToStorageBuffer(bytes)) 16 | XCTAssertEqual(roundtrippedBytes, bytes) 17 | } 18 | 19 | public func testProduceMemoryBuffer() throws { 20 | let bytes: [UInt8] = [1, 2, 3] 21 | let roundtrippedBytes = try WinRTComponent_ByteBuffers.memoryBufferToArray(try WindowsFoundation_MemoryBuffer(bytes)) 22 | XCTAssertEqual(roundtrippedBytes, bytes) 23 | } 24 | 25 | public func testProduceStorageBuffer() throws { 26 | let bytes: [UInt8] = [1, 2, 3] 27 | let roundtrippedBytes = try WinRTComponent_ByteBuffers.storageBufferToArray(try WindowsStorageStreams_Buffer(bytes)) 28 | XCTAssertEqual(roundtrippedBytes, bytes) 29 | } 30 | } -------------------------------------------------------------------------------- /InteropTests/Tests/CollectionTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import WinRTComponent 3 | 4 | class CollectionTests: WinRTTestCase { 5 | func testIteration() throws { 6 | let iterable = try WinRTComponent_Collections.createIterable([3, 2, 1]) 7 | let iterator = try iterable.first() 8 | XCTAssert(try iterator.hasCurrent) 9 | XCTAssertEqual(try iterator.current, 3) 10 | XCTAssert(try iterator.moveNext()) 11 | XCTAssertEqual(try iterator.current, 2) 12 | XCTAssert(try iterator.moveNext()) 13 | XCTAssertEqual(try iterator.current, 1) 14 | XCTAssertFalse(try iterator.moveNext()) 15 | } 16 | } -------------------------------------------------------------------------------- /InteropTests/Tests/DateTimeTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import UWP 3 | import WinRTComponent 4 | import struct Foundation.Date 5 | 6 | class DateTimeTests: WinRTTestCase { 7 | func testTimeSpan() throws { 8 | XCTAssertEqual(try WinRTComponent_DateTimes.fromSeconds(42).timeInterval.rounded(), 42) 9 | XCTAssertEqual(try WinRTComponent_DateTimes.roundToSeconds(WindowsFoundation_TimeSpan(timeInterval: 42)), 42) 10 | } 11 | 12 | func testDateTime() throws { 13 | XCTAssertEqual(try WinRTComponent_DateTimes.fromUTCYearMonthDay(1970, 1, 1).foundationDate.timeIntervalSince1970, 0) 14 | var year: Int32 = 0 15 | var month: Int32 = 0 16 | var day: Int32 = 0 17 | try WinRTComponent_DateTimes.toUTCYearMonthDay(WindowsFoundation_DateTime(foundationDate: Date(timeIntervalSince1970: 0)), &year, &month, &day) 18 | XCTAssertEqual(year, 1970) 19 | XCTAssertEqual(month, 1) 20 | XCTAssertEqual(day, 1) 21 | } 22 | } -------------------------------------------------------------------------------- /InteropTests/Tests/DeprecationTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import WinRTComponent 3 | 4 | class DeprecationTests: XCTestCase { 5 | @available(*, deprecated, message: "Deprecated to allow using deprecated symbols without warnings.") 6 | func testDeprecatedTypesExist() throws { 7 | // We can't validate that they produce deprecated messages at compile-time, 8 | // but we can at least validate that the types have been generated. 9 | _ = WinRTComponent_DeprecatedEnum.one 10 | _ = WinRTComponent_DeprecatedStruct().field 11 | _ = {} as WinRTComponent_DeprecatedDelegate 12 | _ = try (nil as WinRTComponent_IDeprecatedInterface?)?.property 13 | try (nil as WinRTComponent_IDeprecatedInterface?)?.method() 14 | try (nil as WinRTComponent_IDeprecatedInterface?)?.event {} 15 | try WinRTComponent_DeprecatedClass(42).method() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /InteropTests/Tests/FlatModuleTests.swift: -------------------------------------------------------------------------------- 1 | import UWP_Flat 2 | 3 | // Compile-time tests that the UWP_Flat flat module 4 | // exposes short names for types in that module. 5 | fileprivate typealias MemoryBufferExists = MemoryBuffer // From UWP_WindowsFoundation 6 | fileprivate typealias IBufferExists = IBuffer // From UWP_WindowsStorageStreams -------------------------------------------------------------------------------- /InteropTests/Tests/NamespaceModuleTests.swift: -------------------------------------------------------------------------------- 1 | import UWP_WindowsFoundation 2 | 3 | // Compile-time tests that the UWP_WindowsFoundation namespace module 4 | // exposes short names for types in that namespace. 5 | fileprivate typealias MemoryBufferExists = MemoryBuffer -------------------------------------------------------------------------------- /InteropTests/Tests/NullValueTests.swift: -------------------------------------------------------------------------------- 1 | import COM 2 | import XCTest 3 | import WinRTComponent 4 | 5 | class NullValueTests: WinRTTestCase { 6 | func testIsNull() throws { 7 | let minimalClass = try WinRTComponent_MinimalClass() 8 | let minimalInterface = try WinRTComponent_MinimalInterfaceFactory.create() 9 | XCTAssertFalse(try WinRTComponent_NullValues.isObjectNull(minimalClass)) 10 | XCTAssertTrue(try WinRTComponent_NullValues.isObjectNull(nil)) 11 | XCTAssertFalse(try WinRTComponent_NullValues.isInterfaceNull(minimalInterface)) 12 | XCTAssertTrue(try WinRTComponent_NullValues.isInterfaceNull(nil)) 13 | XCTAssertFalse(try WinRTComponent_NullValues.isClassNull(minimalClass)) 14 | XCTAssertTrue(try WinRTComponent_NullValues.isClassNull(nil)) 15 | XCTAssertFalse(try WinRTComponent_NullValues.isDelegateNull({ fatalError() })); 16 | XCTAssertTrue(try WinRTComponent_NullValues.isDelegateNull(nil)); 17 | XCTAssertFalse(try WinRTComponent_NullValues.isReferenceNull(42)); 18 | XCTAssertTrue(try WinRTComponent_NullValues.isReferenceNull(nil)); 19 | } 20 | 21 | func testGetNull() throws { 22 | XCTAssertNil(try NullResult.catch(WinRTComponent_NullValues.getNullObject())) 23 | XCTAssertNil(try NullResult.catch(WinRTComponent_NullValues.getNullInterface())) 24 | XCTAssertNil(try NullResult.catch(WinRTComponent_NullValues.getNullDelegate())) 25 | XCTAssertNil(try NullResult.catch(WinRTComponent_NullValues.getNullClass())) 26 | XCTAssertNil(try WinRTComponent_NullValues.getNullReference()) 27 | } 28 | } -------------------------------------------------------------------------------- /InteropTests/Tests/NumbersTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import WinRTComponent 3 | 4 | class NumberTests: WinRTTestCase { 5 | func testBool() throws { 6 | XCTAssertEqual(try WinRTComponent_Numbers.not(false), true) 7 | } 8 | 9 | func testIntegers() throws { 10 | XCTAssertEqual(try WinRTComponent_Numbers.incrementUInt8(1), 2) 11 | XCTAssertEqual(try WinRTComponent_Numbers.incrementInt16(0xFF), 0x100) 12 | XCTAssertEqual(try WinRTComponent_Numbers.incrementUInt16(0xFF), 0x100) 13 | XCTAssertEqual(try WinRTComponent_Numbers.incrementInt32(0xFFFF), 0x1_0000) 14 | XCTAssertEqual(try WinRTComponent_Numbers.incrementUInt32(0xFFFF), 0x1_0000) 15 | XCTAssertEqual(try WinRTComponent_Numbers.incrementInt64(0xFFFF_FFFF), 0x1_0000_0000) 16 | XCTAssertEqual(try WinRTComponent_Numbers.incrementUInt64(0xFFFF_FFFF), 0x1_0000_0000) 17 | } 18 | 19 | func testSignedIntegerOverflow() throws { 20 | XCTAssertEqual(try WinRTComponent_Numbers.incrementInt16(Int16.max), Int16.min) 21 | XCTAssertEqual(try WinRTComponent_Numbers.incrementInt32(Int32.max), Int32.min) 22 | XCTAssertEqual(try WinRTComponent_Numbers.incrementInt64(Int64.max), Int64.min) 23 | } 24 | 25 | func testUnsignedSignedIntegerOverflow() throws { 26 | XCTAssertEqual(try WinRTComponent_Numbers.incrementUInt8(UInt8.max), 0) 27 | XCTAssertEqual(try WinRTComponent_Numbers.incrementUInt16(UInt16.max), 0) 28 | XCTAssertEqual(try WinRTComponent_Numbers.incrementUInt32(UInt32.max), 0) 29 | XCTAssertEqual(try WinRTComponent_Numbers.incrementUInt64(UInt64.max), 0) 30 | } 31 | 32 | func testSingle() throws { 33 | XCTAssertEqual(try WinRTComponent_Numbers.negateSingle(42), -42) 34 | XCTAssertEqual(try WinRTComponent_Numbers.negateDouble(42), -42) 35 | } 36 | } -------------------------------------------------------------------------------- /InteropTests/Tests/OverloadingTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import COM 3 | import WindowsRuntime 4 | import WinRTComponent 5 | 6 | class OverloadingTests: WinRTTestCase { 7 | func testOverloading() throws { 8 | XCTAssertEqual(try WinRTComponent_OverloadedSum.of(), 0) 9 | XCTAssertEqual(try WinRTComponent_OverloadedSum.of(42), 42) 10 | XCTAssertEqual(try WinRTComponent_OverloadedSum.of(7, 3), 10) 11 | } 12 | } -------------------------------------------------------------------------------- /InteropTests/Tests/PropertyTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import COM 3 | import WindowsRuntime 4 | import WinRTComponent 5 | 6 | class PropertyTests: WinRTTestCase { 7 | func testInstance() throws { 8 | let wrapper = try WinRTComponent_Int32Wrapper() 9 | 10 | func assertGet(expected: Int32) throws { 11 | XCTAssertEqual(try wrapper.getOnly, expected) 12 | XCTAssertEqual(wrapper.getOnly_, expected) 13 | XCTAssertEqual(try wrapper.getSet, expected) 14 | XCTAssertEqual(wrapper.getSet_, expected) 15 | } 16 | 17 | try assertGet(expected: 0) 18 | 19 | try wrapper.getSet(1) 20 | try assertGet(expected: 1) 21 | 22 | wrapper.getSet_ = 2 23 | try assertGet(expected: 2) 24 | } 25 | 26 | func testStatic() throws { 27 | func assertGet(expected: Int32) throws { 28 | XCTAssertEqual(try WinRTComponent_Int32Global.getOnly, expected) 29 | XCTAssertEqual(WinRTComponent_Int32Global.getOnly_, expected) 30 | XCTAssertEqual(try WinRTComponent_Int32Global.getSet, expected) 31 | XCTAssertEqual(WinRTComponent_Int32Global.getSet_, expected) 32 | } 33 | 34 | try WinRTComponent_Int32Global.getSet(0) 35 | try assertGet(expected: 0) 36 | 37 | try WinRTComponent_Int32Global.getSet(1) 38 | try assertGet(expected: 1) 39 | 40 | WinRTComponent_Int32Global.getSet_ = 2 41 | try assertGet(expected: 2) 42 | } 43 | } -------------------------------------------------------------------------------- /InteropTests/Tests/ReferenceBoxingTests.swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime 2 | import WinRTComponent 3 | import XCTest 4 | 5 | class ReferenceBoxingTests: WinRTTestCase { 6 | func testRoundTripOfPrimitiveWithIdentityBinding() throws { 7 | let original = Int32(42) 8 | XCTAssertEqual(try XCTUnwrap(WinRTComponent_ReferenceBoxing.boxInt32(original)), original) 9 | XCTAssertEqual(try WinRTComponent_ReferenceBoxing.unboxInt32(Optional(original)), original) 10 | XCTAssertThrowsError(try WinRTComponent_ReferenceBoxing.unboxInt32(nil)) 11 | } 12 | 13 | func testRoundTripOfEnum() throws { 14 | let original = WinRTComponent_MinimalEnum.one 15 | XCTAssertEqual(try XCTUnwrap(WinRTComponent_ReferenceBoxing.boxMinimalEnum(original)), original) 16 | XCTAssertEqual(try WinRTComponent_ReferenceBoxing.unboxMinimalEnum(Optional(original)), original) 17 | XCTAssertThrowsError(try WinRTComponent_ReferenceBoxing.unboxMinimalEnum(nil)) 18 | } 19 | 20 | func testRoundTripOfStruct() throws { 21 | let original = WinRTComponent_MinimalStruct(field: 42) 22 | XCTAssertEqual(try XCTUnwrap(WinRTComponent_ReferenceBoxing.boxMinimalStruct(original)), original) 23 | XCTAssertEqual(try WinRTComponent_ReferenceBoxing.unboxMinimalStruct(Optional(original)), original) 24 | XCTAssertThrowsError(try WinRTComponent_ReferenceBoxing.unboxMinimalStruct(nil)) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /InteropTests/Tests/StringTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import COM 3 | import WindowsRuntime 4 | import WinRTComponent 5 | 6 | class StringTests: WinRTTestCase { 7 | func testEmpty() throws { 8 | XCTAssertEqual(try WinRTComponent_Strings.roundtrip(""), "") 9 | } 10 | 11 | func testEmbeddedNull() throws { 12 | XCTAssertEqual(try WinRTComponent_Strings.roundtrip("\0"), "\0") 13 | } 14 | 15 | func testNonBasicMultilingualPlane() throws { 16 | XCTAssertEqual(try WinRTComponent_Strings.roundtrip("😂"), "😂") // U+1F602 FACE WITH TEARS OF JOY 17 | } 18 | 19 | func testChars() throws { 20 | XCTAssertEqual(try WinRTComponent_Strings.roundtripChar(Char16(65)), Char16(65)) // ascii 'a' 21 | XCTAssertEqual(try WinRTComponent_Strings.roundtripChar(Char16(0)), Char16(0)) // NUL 22 | XCTAssertEqual(try WinRTComponent_Strings.roundtripChar(Char16(0x0142)), Char16(0x0142)) // non-ascii 'Ł' 23 | XCTAssertEqual(try WinRTComponent_Strings.roundtripChar(Char16(0xE000)), Char16(0xE000)) // private use 24 | XCTAssertEqual(try WinRTComponent_Strings.roundtripChar(Char16(0xDC00)), Char16(0xDC00)) // low surrogate 25 | XCTAssertEqual(try WinRTComponent_Strings.roundtripChar(Char16(0xD800)), Char16(0xD800)) // high surrogate 26 | } 27 | 28 | func testMalformedUTF16() throws { 29 | XCTAssertEqual( 30 | try WinRTComponent_Strings.fromChars([Char16(0xDC00)]), // Mismatched low surrogate 31 | "�") // U+FFFD REPLACEMENT CHARACTER 32 | } 33 | } -------------------------------------------------------------------------------- /InteropTests/Tests/WeakReferenceTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import WindowsRuntime 3 | import WinRTComponent 4 | 5 | class WeakReferenceTests: WinRTTestCase { 6 | func testNulledWhenUnreferencedFromSwift() throws { 7 | var target: WinRTComponent_MinimalClass! = try WinRTComponent_MinimalClass() 8 | let weakReference = try WeakReference(target) 9 | XCTAssertNotNil(try weakReference.resolve()) 10 | target = nil 11 | XCTAssertNil(try weakReference.resolve()) 12 | } 13 | 14 | func testNulledWhenUnreferencedFromWinRT() throws { 15 | var target: WinRTComponent_MinimalClass! = try WinRTComponent_MinimalClass() 16 | let strongReferencer = try WinRTComponent_ObjectReferencer(target) 17 | let weakReference = try WeakReference(target) 18 | target = nil 19 | 20 | XCTAssertNotNil(try NullResult.catch(strongReferencer.target)) 21 | XCTAssertNotNil(try weakReference.resolve()) 22 | 23 | try strongReferencer.clear() 24 | 25 | XCTAssertNil(try NullResult.catch(strongReferencer.target)) 26 | XCTAssertNil(try weakReference.resolve()) 27 | } 28 | 29 | func testThroughIWeakReferenceSource() throws { 30 | var target: WinRTComponent_MinimalClass! = try WinRTComponent_MinimalClass() 31 | var weakReferenceSource: IWeakReferenceSource! = try target.queryInterface(IWeakReferenceSourceBinding.self) 32 | let weakReference = try weakReferenceSource.getWeakReference() 33 | XCTAssertNotNil(try weakReference.resolve()) 34 | target = nil 35 | weakReferenceSource = nil 36 | XCTAssertNil(try weakReference.resolve()) 37 | } 38 | } -------------------------------------------------------------------------------- /InteropTests/Tests/WinRTTestCase.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import WindowsRuntime 3 | 4 | class WinRTTestCase: XCTestCase { 5 | // Only created once before the first test of any test case runs, 6 | // and never freed because we don't know when we've run the last test, 7 | // and reinitializing WinRT could invalidate cached activation factories. 8 | private static let initialization: Result 9 | = Result { try WinRTInitialization(multithreaded: true) } 10 | 11 | override class func setUp() { 12 | // Enforce that the static initializer runs before any tests. 13 | _ = try? initialization.get() 14 | } 15 | 16 | override func setUpWithError() throws { 17 | _ = try Self.initialization.get() 18 | } 19 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated code goes here for the Swift build. Ignore it. 2 | Projection/ -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 21, 6 | "patch": 0 7 | }, 8 | "configurePresets": [ 9 | { 10 | "name": "debug", 11 | "displayName": "Debug", 12 | "generator": "Ninja", 13 | "binaryDir": "${sourceDir}/build/debug", 14 | "cacheVariables": { 15 | "CMAKE_BUILD_TYPE": "Debug", 16 | "CMAKE_CXX_COMPILER": "cl", 17 | "CMAKE_CXX_FLAGS": "/std:c++latest /W4 /EHsc" 18 | } 19 | } 20 | ], 21 | "buildPresets": [ 22 | { 23 | "name": "debug", 24 | "displayName": "Debug", 25 | "configurePreset": "debug" 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/Arrays.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Arrays.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct Arrays 7 | { 8 | static hstring GetLast(array_view value) 9 | { 10 | return value.back(); 11 | } 12 | 13 | static com_array Make(hstring const& a, hstring const& b) 14 | { 15 | return { a, b }; 16 | } 17 | 18 | static void Output(hstring const& a, hstring const& b, com_array& array) 19 | { 20 | array = { a, b }; 21 | } 22 | 23 | static void SwapFirstLast(array_view array) 24 | { 25 | std::swap(array.front(), array.back()); 26 | } 27 | }; 28 | } 29 | 30 | namespace winrt::WinRTComponent::factory_implementation 31 | { 32 | struct Arrays : ArraysT 33 | { 34 | }; 35 | } 36 | 37 | #include "Arrays.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/ByteBuffers.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ByteBuffers.g.h" 3 | #include 4 | 5 | namespace winrt::WinRTComponent::implementation 6 | { 7 | struct ByteBuffers 8 | { 9 | static com_array MemoryBufferToArray(winrt::Windows::Foundation::IMemoryBuffer const& buffer) 10 | { 11 | auto bufferReference = buffer.CreateReference(); 12 | auto data = bufferReference.data(); 13 | return { data, data + bufferReference.Capacity() }; 14 | } 15 | 16 | static com_array StorageBufferToArray(winrt::Windows::Storage::Streams::IBuffer const& buffer) 17 | { 18 | auto data = buffer.data(); 19 | return { data, data + buffer.Length() }; 20 | } 21 | 22 | static winrt::Windows::Foundation::IMemoryBuffer ArrayToMemoryBuffer(array_view bytes) 23 | { 24 | winrt::Windows::Foundation::MemoryBuffer buffer(bytes.size()); 25 | memcpy(buffer.CreateReference().data(), bytes.data(), bytes.size()); 26 | return buffer; 27 | } 28 | 29 | static winrt::Windows::Storage::Streams::IBuffer ArrayToStorageBuffer(array_view bytes) 30 | { 31 | winrt::Windows::Storage::Streams::Buffer buffer(bytes.size()); 32 | memcpy(buffer.data(), bytes.data(), bytes.size()); 33 | buffer.Length(bytes.size()); 34 | return buffer; 35 | } 36 | }; 37 | } 38 | 39 | namespace winrt::WinRTComponent::factory_implementation 40 | { 41 | struct ByteBuffers : ByteBuffersT 42 | { 43 | }; 44 | } 45 | 46 | #include "ByteBuffers.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21.0) 2 | project(WinRTComponentDll LANGUAGES CXX) 3 | 4 | if(NOT DEFINED WINRTCOMPONENT_WINMD) 5 | message(FATAL_ERROR "WINRTCOMPONENT_WINMD must be defined") 6 | endif() 7 | 8 | # Generate the C++/WinRT boilerplate 9 | message(STATUS "Generating C++/WinRT boilerplate for WinRTComponent...") 10 | set(CPPWINRT_EXE_NATIVE "$ENV{WindowsSdkVerBinPath}$ENV{VSCMD_ARG_HOST_ARCH}\\cppwinrt.exe") 11 | if(NOT EXISTS "${CPPWINRT_EXE_NATIVE}") 12 | message(FATAL_ERROR "Could not find cppwinrt.exe at ${CPPWINRT_EXE_NATIVE}") 13 | endif() 14 | 15 | cmake_path(CONVERT "${WINRTCOMPONENT_WINMD}" TO_NATIVE_PATH_LIST WINRTCOMPONENT_WINMD_NATIVE) 16 | string(REPLACE "\\" "" WINSDK_VERSION "$ENV{WindowsSDKVersion}") 17 | set(CPPWINRT_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/CppWinRT") 18 | cmake_path(CONVERT "${CPPWINRT_GENERATED_DIR}" TO_NATIVE_PATH_LIST CPPWINRT_GENERATED_DIR_NATIVE) 19 | file(REMOVE_RECURSE "${CPPWINRT_GENERATED_DIR}") 20 | execute_process( 21 | COMMAND "${CPPWINRT_EXE_NATIVE}" 22 | -input "${WINRTCOMPONENT_WINMD_NATIVE}" 23 | -reference "${WINSDK_VERSION}" 24 | -component "${CPPWINRT_GENERATED_DIR_NATIVE}" -overwrite -optimize 25 | -output "${CPPWINRT_GENERATED_DIR_NATIVE}" 26 | COMMAND_ERROR_IS_FATAL ANY) 27 | 28 | # Build WinRTComponent.dll 29 | file(GLOB SOURCES "*.cpp") 30 | add_library(WinRTComponent SHARED 31 | ${SOURCES} 32 | "${CPPWINRT_GENERATED_DIR}/module.g.cpp" # Other .g.cpp files are #included by our .cpp files 33 | WinRTComponent.def) 34 | target_include_directories(WinRTComponent PRIVATE 35 | "${CMAKE_CURRENT_SOURCES_DIR}" 36 | "${CPPWINRT_GENERATED_DIR}") 37 | target_precompile_headers(WinRTComponent PRIVATE pch.h) -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/Collections.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Collections.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct Collections 7 | { 8 | static winrt::Windows::Foundation::Collections::IIterable CreateIterable(array_view values) 9 | { 10 | return winrt::single_threaded_vector(std::vector(values.begin(), values.end())); 11 | } 12 | 13 | static winrt::Windows::Foundation::Collections::IVector CreateVector(array_view values) 14 | { 15 | return winrt::single_threaded_vector(std::vector(values.begin(), values.end())); 16 | } 17 | 18 | static com_array IterableToArray(winrt::Windows::Foundation::Collections::IIterable const& iterable) 19 | { 20 | std::vector result; 21 | for (auto iterator = iterable.First(); iterator.HasCurrent(); iterator.MoveNext()) 22 | result.push_back(iterator.Current()); 23 | return com_array(result); 24 | } 25 | }; 26 | } 27 | 28 | namespace winrt::WinRTComponent::factory_implementation 29 | { 30 | struct Collections : CollectionsT 31 | { 32 | }; 33 | } 34 | 35 | #include "Collections.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/DateTimes.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "DateTimes.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct DateTimes 7 | { 8 | static winrt::Windows::Foundation::TimeSpan FromSeconds(int32_t seconds) 9 | { 10 | return std::chrono::seconds(seconds); 11 | } 12 | 13 | static int32_t RoundToSeconds(winrt::Windows::Foundation::TimeSpan const& timeSpan) 14 | { 15 | return static_cast(std::chrono::round(timeSpan).count()); 16 | } 17 | 18 | static winrt::Windows::Foundation::DateTime FromUTCYearMonthDay(int32_t year, int32_t month, int32_t day) 19 | { 20 | tm components = {}; 21 | components.tm_year = year - 1900; 22 | components.tm_mon = month - 1; 23 | components.tm_mday = day; 24 | auto const time = _mkgmtime64(&components); 25 | if (time == -1) throw winrt::hresult_invalid_argument(L"Invalid date"); 26 | return winrt::clock::from_time_t(time); 27 | } 28 | 29 | static void ToUTCYearMonthDay(winrt::Windows::Foundation::DateTime const& dateTime, int32_t& year, int32_t& month, int32_t& day) 30 | { 31 | auto const time = winrt::clock::to_time_t(dateTime); 32 | tm components; 33 | if (_gmtime64_s(&components, &time) != 0) throw winrt::hresult_invalid_argument(L"Failed to convert to a date"); 34 | year = components.tm_year + 1900; 35 | month = components.tm_mon + 1; 36 | day = components.tm_mday; 37 | } 38 | }; 39 | } 40 | 41 | namespace winrt::WinRTComponent::factory_implementation 42 | { 43 | struct DateTimes : DateTimesT 44 | { 45 | }; 46 | } 47 | 48 | #include "DateTimes.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/DeprecatedClass.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "DeprecatedClass.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct DeprecatedClass : DeprecatedClassT 7 | { 8 | DeprecatedClass(int32_t) {} 9 | void Method() {} 10 | }; 11 | } 12 | 13 | namespace winrt::WinRTComponent::factory_implementation 14 | { 15 | struct DeprecatedClass : DeprecatedClassT 16 | { 17 | }; 18 | } 19 | 20 | #include "DeprecatedClass.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/DestructionCallback.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "DestructionCallback.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct DestructionCallback : DestructionCallbackT 7 | { 8 | DestructionCallback(winrt::WinRTComponent::MinimalDelegate const& callback) : m_callback(callback) {} 9 | ~DestructionCallback() { m_callback(); } 10 | 11 | winrt::WinRTComponent::MinimalDelegate m_callback; 12 | }; 13 | } 14 | namespace winrt::WinRTComponent::factory_implementation 15 | { 16 | struct DestructionCallback : DestructionCallbackT 17 | { 18 | }; 19 | } 20 | 21 | #include "DestructionCallback.g.cpp" 22 | -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/Errors.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Errors.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct Errors 7 | { 8 | static void FailWith(winrt::hresult const& hr, winrt::hstring const& message) 9 | { 10 | throw winrt::hresult_error(hr, message); 11 | } 12 | 13 | static hstring NotImplementedProperty() 14 | { 15 | throw winrt::hresult_not_implemented(); 16 | } 17 | 18 | static void NotImplementedProperty(hstring const&) 19 | { 20 | throw winrt::hresult_not_implemented(); 21 | } 22 | 23 | static void Call(winrt::WinRTComponent::MinimalDelegate const& callee) 24 | { 25 | callee(); 26 | } 27 | 28 | static winrt::hresult CatchHResult(winrt::WinRTComponent::MinimalDelegate const& callee) 29 | { 30 | try { callee(); } 31 | catch (const winrt::hresult_error& error) { return error.code(); } 32 | return winrt::hresult(); 33 | } 34 | 35 | static winrt::hstring CatchMessage(winrt::WinRTComponent::MinimalDelegate const& callee) 36 | { 37 | try { callee(); } 38 | catch (const winrt::hresult_error& error) { return error.message(); } 39 | return winrt::hstring(); 40 | } 41 | }; 42 | } 43 | 44 | namespace winrt::WinRTComponent::factory_implementation 45 | { 46 | struct Errors : ErrorsT 47 | { 48 | }; 49 | } 50 | 51 | #include "Errors.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/ForCustomActivationFactoryResolution.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ForCustomActivationFactoryResolution.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct ForCustomActivationFactoryResolution 7 | { 8 | static void Method() {} 9 | }; 10 | } 11 | 12 | namespace winrt::WinRTComponent::factory_implementation 13 | { 14 | struct ForCustomActivationFactoryResolution : ForCustomActivationFactoryResolutionT 15 | { 16 | }; 17 | } 18 | 19 | #include "ForCustomActivationFactoryResolution.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/Int32Global.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Int32Global.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct Int32Global 7 | { 8 | static int32_t GetOnly() { return _value; } 9 | static int32_t GetSet() { return _value; } 10 | static void GetSet(int32_t value) { _value = value; } 11 | 12 | private: 13 | static int32_t _value; 14 | }; 15 | 16 | int32_t Int32Global::_value = 0; 17 | } 18 | 19 | namespace winrt::WinRTComponent::factory_implementation 20 | { 21 | struct Int32Global : Int32GlobalT 22 | { 23 | }; 24 | } 25 | 26 | #include "Int32Global.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/Int32Wrapper.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Int32Wrapper.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct Int32Wrapper : Int32WrapperT 7 | { 8 | int32_t GetSet() { return _value; } 9 | void GetSet(int32_t value) { _value = value; } 10 | int32_t GetOnly() { return _value; } 11 | 12 | private: 13 | int32_t _value = 0; 14 | }; 15 | } 16 | 17 | namespace winrt::WinRTComponent::factory_implementation 18 | { 19 | struct Int32Wrapper : Int32WrapperT 20 | { 21 | }; 22 | } 23 | 24 | #include "Int32Wrapper.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/InterfaceCasting.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "InterfaceCasting.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct InterfaceCasting 7 | { 8 | static winrt::WinRTComponent::IMinimalInterface AsMinimalInterface(winrt::Windows::Foundation::IInspectable object) 9 | { 10 | return object.as(); 11 | } 12 | }; 13 | } 14 | 15 | namespace winrt::WinRTComponent::factory_implementation 16 | { 17 | struct InterfaceCasting : InterfaceCastingT 18 | { 19 | }; 20 | } 21 | 22 | #include "InterfaceCasting.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/MinimalClass.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MinimalClass.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct MinimalClass : MinimalClassT 7 | { 8 | void Method() {} 9 | }; 10 | } 11 | 12 | namespace winrt::WinRTComponent::factory_implementation 13 | { 14 | struct MinimalClass : MinimalClassT 15 | { 16 | }; 17 | } 18 | 19 | #include "MinimalClass.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/MinimalInterfaceFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "MinimalInterfaceFactory.g.h" 3 | 4 | namespace 5 | { 6 | struct MinimalInterfaceImplementation : winrt::implements 7 | { 8 | void Method() {} 9 | }; 10 | } 11 | 12 | namespace winrt::WinRTComponent::implementation 13 | { 14 | struct MinimalInterfaceFactory 15 | { 16 | static winrt::WinRTComponent::IMinimalInterface Create() 17 | { 18 | return winrt::make(); 19 | } 20 | }; 21 | } 22 | 23 | namespace winrt::WinRTComponent::factory_implementation 24 | { 25 | struct MinimalInterfaceFactory : MinimalInterfaceFactoryT 26 | { 27 | }; 28 | } 29 | 30 | #include "MinimalInterfaceFactory.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/NullValues.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "NullValues.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct NullValues 7 | { 8 | static bool IsObjectNull(winrt::Windows::Foundation::IInspectable const& value) { return value == nullptr; } 9 | static bool IsInterfaceNull(winrt::WinRTComponent::IMinimalInterface const& value) { return value == nullptr; } 10 | static bool IsClassNull(winrt::WinRTComponent::MinimalClass const& value) { return value == nullptr; } 11 | static bool IsDelegateNull(winrt::WinRTComponent::MinimalDelegate const& value) { return value == nullptr; } 12 | static bool IsReferenceNull(winrt::Windows::Foundation::IReference const& value) { return value == nullptr; } 13 | static winrt::Windows::Foundation::IInspectable GetNullObject() { return nullptr; } 14 | static winrt::WinRTComponent::IMinimalInterface GetNullInterface() { return nullptr; } 15 | static winrt::WinRTComponent::MinimalClass GetNullClass() { return nullptr; } 16 | static winrt::WinRTComponent::MinimalDelegate GetNullDelegate() { return nullptr; } 17 | static winrt::Windows::Foundation::IReference GetNullReference() { return nullptr; } 18 | }; 19 | } 20 | 21 | namespace winrt::WinRTComponent::factory_implementation 22 | { 23 | struct NullValues : NullValuesT 24 | { 25 | }; 26 | } 27 | 28 | #include "NullValues.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/Numbers.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Numbers.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct Numbers 7 | { 8 | static bool Not(bool value) { return !value; } 9 | static uint8_t IncrementUInt8(uint8_t value) { return value + 1; } 10 | static int16_t IncrementInt16(int16_t value) { return value + 1; } 11 | static uint16_t IncrementUInt16(uint16_t value) { return value + 1; } 12 | static int32_t IncrementInt32(int32_t value) { return value + 1; } 13 | static uint32_t IncrementUInt32(uint32_t value) { return value + 1; } 14 | static int64_t IncrementInt64(int64_t value) { return value + 1; } 15 | static uint64_t IncrementUInt64(uint64_t value) { return value + 1; } 16 | static float NegateSingle(float value) { return -value; } 17 | static double NegateDouble(double value) { return -value; } 18 | }; 19 | } 20 | 21 | namespace winrt::WinRTComponent::factory_implementation 22 | { 23 | struct Numbers : NumbersT 24 | { 25 | }; 26 | } 27 | 28 | #include "Numbers.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/ObjectReferencer.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ObjectReferencer.g.h" 3 | #include 4 | 5 | namespace winrt::WinRTComponent::implementation 6 | { 7 | struct ObjectReferencer : ObjectReferencerT 8 | { 9 | ObjectReferencer(winrt::Windows::Foundation::IInspectable const& obj) 10 | { 11 | m_object = obj; 12 | } 13 | 14 | winrt::Windows::Foundation::IInspectable Target() { return m_object; } 15 | void Clear() { m_object = nullptr; } 16 | 17 | uint32_t CallAddRef() 18 | { 19 | return winrt::get_unknown(m_object)->AddRef(); 20 | } 21 | 22 | uint32_t CallRelease() 23 | { 24 | return winrt::get_unknown(m_object)->Release(); 25 | } 26 | 27 | private: 28 | winrt::Windows::Foundation::IInspectable m_object = nullptr; 29 | }; 30 | } 31 | 32 | namespace winrt::WinRTComponent::factory_implementation 33 | { 34 | struct ObjectReferencer : ObjectReferencerT 35 | { 36 | }; 37 | } 38 | 39 | #include "ObjectReferencer.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/OverloadedSum.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "OverloadedSum.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct OverloadedSum : OverloadedSumT 7 | { 8 | OverloadedSum() : m_result(0) {} 9 | OverloadedSum(int32_t a) : m_result(a) {} 10 | OverloadedSum(int32_t a, int32_t b) : m_result(a + b) {} 11 | 12 | int32_t Result() { return m_result; } 13 | 14 | static int32_t Of() { return 0; } 15 | static int32_t Of(int32_t a) { return a; } 16 | static int32_t Of(int32_t a, int32_t b) { return a + b; } 17 | 18 | private: 19 | int32_t m_result = 0; 20 | }; 21 | } 22 | 23 | namespace winrt::WinRTComponent::factory_implementation 24 | { 25 | struct OverloadedSum : OverloadedSumT 26 | { 27 | }; 28 | } 29 | 30 | #include "OverloadedSum.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/ReferenceBoxing.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ReferenceBoxing.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct ReferenceBoxing 7 | { 8 | static winrt::Windows::Foundation::IReference BoxInt32(int32_t value) 9 | { 10 | return { value }; 11 | } 12 | 13 | static int32_t UnboxInt32(winrt::Windows::Foundation::IReference const& value) 14 | { 15 | if (value == nullptr) throw winrt::hresult_invalid_argument(); 16 | return value.Value(); 17 | } 18 | 19 | static winrt::Windows::Foundation::IReference BoxMinimalEnum(winrt::WinRTComponent::MinimalEnum const& value) 20 | { 21 | return { value }; 22 | } 23 | 24 | static winrt::WinRTComponent::MinimalEnum UnboxMinimalEnum(winrt::Windows::Foundation::IReference const& value) 25 | { 26 | if (value == nullptr) throw winrt::hresult_invalid_argument(); 27 | return value.Value(); 28 | } 29 | 30 | static winrt::Windows::Foundation::IReference BoxMinimalStruct(winrt::WinRTComponent::MinimalStruct const& value) 31 | { 32 | return { value }; 33 | } 34 | 35 | static winrt::WinRTComponent::MinimalStruct UnboxMinimalStruct(winrt::Windows::Foundation::IReference const& value) 36 | { 37 | if (value == nullptr) throw winrt::hresult_invalid_argument(); 38 | return value.Value(); 39 | } 40 | }; 41 | } 42 | 43 | namespace winrt::WinRTComponent::factory_implementation 44 | { 45 | struct ReferenceBoxing : ReferenceBoxingT 46 | { 47 | }; 48 | } 49 | 50 | #include "ReferenceBoxing.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/ShadowingConstructors.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | // C++/WinRT struggles with a derived class having a default constructor which delegates to a base class constructor with a parameter. 4 | // So just stub out the exports here as we won't instantiate the classes anyways. 5 | void * __cdecl winrt_make_WinRTComponent_ShadowingConstructorsBase() { return nullptr; } 6 | void * __cdecl winrt_make_WinRTComponent_ShadowingConstructorsDerived() { return nullptr; } 7 | -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/Strings.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Strings.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct Strings 7 | { 8 | static hstring Roundtrip(hstring const& value) { return value; } 9 | static char16_t RoundtripChar(char16_t value) { return value; } 10 | 11 | static hstring FromChars(array_view chars) 12 | { 13 | static_assert(sizeof(wchar_t) == sizeof(char16_t)); 14 | return hstring( 15 | reinterpret_cast(chars.data()), 16 | static_cast(chars.size())); 17 | } 18 | 19 | static com_array ToChars(hstring const& value) 20 | { 21 | static_assert(sizeof(wchar_t) == sizeof(char16_t)); 22 | return com_array( 23 | reinterpret_cast(value.data()), 24 | reinterpret_cast(value.data()) + value.size()); 25 | } 26 | }; 27 | } 28 | 29 | namespace winrt::WinRTComponent::factory_implementation 30 | { 31 | struct Strings : StringsT 32 | { 33 | }; 34 | } 35 | 36 | #include "Strings.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/Structs.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Structs.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct Structs 7 | { 8 | static winrt::WinRTComponent::Struct Make(int32_t int32, hstring const& string, winrt::Windows::Foundation::IReference const& reference, winrt::WinRTComponent::LeafStruct const& nested) 9 | { 10 | return { int32, string, reference, nested }; 11 | } 12 | 13 | static int32_t GetInt32(winrt::WinRTComponent::Struct const& value) { return value.Int32; } 14 | static hstring GetString(winrt::WinRTComponent::Struct const& value) { return value.String; } 15 | static winrt::Windows::Foundation::IReference GetReference(winrt::WinRTComponent::Struct const& value) { return value.Reference; } 16 | static winrt::WinRTComponent::LeafStruct GetNested(winrt::WinRTComponent::Struct const& value) { return value.Nested; } 17 | 18 | static void Output(int32_t int32, hstring const& string, winrt::Windows::Foundation::IReference const& reference, winrt::WinRTComponent::LeafStruct const& nested, winrt::WinRTComponent::Struct& value) 19 | { 20 | value = { int32, string, reference, nested }; 21 | } 22 | 23 | static winrt::WinRTComponent::Struct ReturnRefConstArgument(const winrt::WinRTComponent::Struct& value) 24 | { 25 | return value; 26 | } 27 | }; 28 | } 29 | 30 | namespace winrt::WinRTComponent::factory_implementation 31 | { 32 | struct Structs : StructsT 33 | { 34 | }; 35 | } 36 | 37 | #include "Structs.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/SwiftAttributes.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SwiftAttributes.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct SwiftAttributes 7 | { 8 | static void MainActor() {} 9 | static void AvailableFromSwift1() {} 10 | static int32_t AvailableFromSwift1WithDiscardableResult() { return 42; } 11 | }; 12 | } 13 | 14 | namespace winrt::WinRTComponent::factory_implementation 15 | { 16 | struct SwiftAttributes : SwiftAttributesT 17 | { 18 | }; 19 | } 20 | 21 | #include "SwiftAttributes.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/WeakReferencer.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "WeakReferencer.g.h" 3 | 4 | namespace winrt::WinRTComponent::implementation 5 | { 6 | struct WeakReferencer : WeakReferencerT 7 | { 8 | WeakReferencer(winrt::Windows::Foundation::IInspectable const& target) 9 | { 10 | this->target = winrt::make_weak(target); 11 | } 12 | 13 | winrt::Windows::Foundation::IInspectable Target() 14 | { 15 | return target.get(); 16 | } 17 | 18 | private: 19 | winrt::weak_ref target; 20 | }; 21 | } 22 | 23 | namespace winrt::WinRTComponent::factory_implementation 24 | { 25 | struct WeakReferencer : WeakReferencerT 26 | { 27 | }; 28 | } 29 | 30 | #include "WeakReferencer.g.cpp" -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/WinRTComponent.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE 3 | DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE 4 | -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Dll/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/Projection.json: -------------------------------------------------------------------------------- 1 | { 2 | "modules": { 3 | "UWP": { 4 | "assemblies": [ 5 | "Windows.*" 6 | ], 7 | "types": [ 8 | "Windows.Foundation.MemoryBuffer", 9 | "Windows.Storage.Streams.Buffer" 10 | ], 11 | "spmLibraryName": "SwiftUWP", 12 | "cmakeTargetName": "SwiftUWP" 13 | }, 14 | "WinRTComponent": { 15 | "assemblies": [ 16 | "WinRTComponent" 17 | ], 18 | "spmLibraryName": "SwiftWinRTComponent", 19 | "cmakeTargetName": "SwiftWinRTComponent", 20 | "fileNameInManifest": "WinRTComponent.dll" 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/Arrays.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | static runtimeclass Arrays 6 | { 7 | // Use an element type involving allocations, 8 | // and assume that POD elements and other objects behave the same. 9 | static String GetLast(String[] value); 10 | static String[] Make(String a, String b); 11 | static void Output(String a, String b, out String[] array); 12 | static void SwapFirstLast(ref String[] array); 13 | }; 14 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/ByteBuffers.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | static runtimeclass ByteBuffers 4 | { 5 | static UInt8[] MemoryBufferToArray(Windows.Foundation.IMemoryBuffer buffer); 6 | static UInt8[] StorageBufferToArray(Windows.Storage.Streams.IBuffer buffer); 7 | 8 | static Windows.Foundation.IMemoryBuffer ArrayToMemoryBuffer(UInt8[] bytes); 9 | static Windows.Storage.Streams.IBuffer ArrayToStorageBuffer(UInt8[] bytes); 10 | } 11 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/ClassInheritance.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | unsealed runtimeclass MinimalBaseClass 4 | { 5 | MinimalBaseClass(); 6 | overridable String TypeName { get; }; 7 | }; 8 | 9 | unsealed runtimeclass MinimalUnsealedDerivedClass : MinimalBaseClass 10 | { 11 | MinimalUnsealedDerivedClass(); 12 | }; 13 | 14 | runtimeclass MinimalSealedDerivedClass : MinimalBaseClass 15 | { 16 | MinimalSealedDerivedClass(); 17 | 18 | // Avoids error MIDL5053 : [msg]empty runtime class cannot have the [composable] or [activatable] attribute [context] 19 | void Dummy(); 20 | }; 21 | 22 | static runtimeclass MinimalBaseClassHierarchy 23 | { 24 | static MinimalBaseClass CreateBase(); 25 | static MinimalUnsealedDerivedClass CreateUnsealedDerived(); 26 | static MinimalBaseClass CreateUnsealedDerivedAsBase(); 27 | static MinimalSealedDerivedClass CreateSealedDerived(); 28 | static MinimalBaseClass CreateSealedDerivedAsBase(); 29 | static MinimalBaseClass CreatePrivateDerived(); 30 | static MinimalBaseClass Passthrough(MinimalBaseClass value); 31 | static String GetTypeName(MinimalBaseClass value); 32 | }; 33 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/Collections.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | static runtimeclass Collections 4 | { 5 | static Windows.Foundation.Collections.IIterable CreateIterable(Int32[] values); 6 | static Windows.Foundation.Collections.IVector CreateVector(Int32[] values); 7 | 8 | static Int32[] IterableToArray(Windows.Foundation.Collections.IIterable iterable); 9 | }; 10 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/DateTimes.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | static runtimeclass DateTimes 4 | { 5 | static Windows.Foundation.TimeSpan FromSeconds(Int32 seconds); 6 | static Int32 RoundToSeconds(Windows.Foundation.TimeSpan timeSpan); 7 | static Windows.Foundation.DateTime FromUTCYearMonthDay(Int32 year, Int32 month, Int32 day); 8 | static void ToUTCYearMonthDay(Windows.Foundation.DateTime dateTime, out Int32 year, out Int32 month, out Int32 day); 9 | } 10 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/Deprecation.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | [deprecated("enum", deprecate, 1.0)] 6 | enum DeprecatedEnum 7 | { 8 | [deprecated("enumerant", deprecate, 1.0)] 9 | One = 1 10 | }; 11 | 12 | [deprecated("struct", deprecate, 1.0)] 13 | struct DeprecatedStruct 14 | { 15 | [deprecated("field", deprecate, 1.0)] 16 | Int32 Field; 17 | }; 18 | 19 | [deprecated("delegate", deprecate, 1.0)] 20 | delegate void DeprecatedDelegate(); 21 | 22 | [deprecated("interface", deprecate, 1.0)] 23 | interface IDeprecatedInterface 24 | { 25 | [deprecated("property", deprecate, 1.0)] 26 | Int32 Property { get; set; }; 27 | 28 | [deprecated("method", deprecate, 1.0)] 29 | void Method(); 30 | 31 | [deprecated("event", deprecate, 1.0)] 32 | event MinimalDelegate Event; 33 | } 34 | 35 | [deprecated("class", deprecate, 1.0)] 36 | runtimeclass DeprecatedClass 37 | { 38 | // WinMD (or idl?) does not support deprecating the default constructor, 39 | // since it uses a shared definition from IActivationFactory. 40 | [deprecated("constructor", deprecate, 1.0)] 41 | DeprecatedClass(Int32 i); 42 | 43 | [deprecated("classmethod", deprecate, 1.0)] 44 | void Method(); 45 | } 46 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/DestructionCallback.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | [default_interface] 6 | unsealed runtimeclass DestructionCallback 7 | { 8 | DestructionCallback(MinimalDelegate callback); 9 | }; 10 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/DocumentationComments.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | enum DocumentationComments 4 | { 5 | // Regression test for https://github.com/tristanlabelle/swift-winrt/issues/356 6 | NewLineInSummary, 7 | }; 8 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/Enums.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | enum SignedEnum 4 | { 5 | Min = -2147483648, 6 | NegativeOne = -1, 7 | Zero = 0, 8 | One = 1, 9 | Max = 2147483647 10 | }; 11 | 12 | [flags] 13 | enum FlagsEnum 14 | { 15 | None = 0, 16 | Bit0 = 1, 17 | Bit16 = 0x10000, 18 | All = 0xFFFFFFFF, 19 | }; 20 | 21 | [attributeusage(target_enum)] 22 | attribute SwiftEnumAttribute {} 23 | 24 | [SwiftEnum] 25 | enum SwiftEnum 26 | { 27 | Zero = 0, 28 | One = 1 29 | }; 30 | 31 | // Regression test for https://github.com/tristanlabelle/swift-winrt/issues/330 32 | interface IFlagsEnumParam { 33 | void Set(FlagsEnum value); 34 | }; 35 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/Errors.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | static runtimeclass Errors 6 | { 7 | static void FailWith(Windows.Foundation.HResult hr, String message); 8 | static String NotImplementedProperty; 9 | static void Call(MinimalDelegate callee); 10 | static Windows.Foundation.HResult CatchHResult(MinimalDelegate callee); 11 | static String CatchMessage(MinimalDelegate callee); 12 | }; 13 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/Events.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | interface IEventSource 6 | { 7 | event MinimalDelegate Event; 8 | void Fire(); 9 | }; 10 | 11 | interface IEventCounter 12 | { 13 | Int32 Count { get; }; 14 | void Detach(); 15 | }; 16 | 17 | static runtimeclass Events 18 | { 19 | static IEventSource CreateSource(); 20 | static IEventCounter CreateCounter(IEventSource source); 21 | }; 22 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/ForCustomActivationFactoryResolution.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | // Only use this type once, as part of a custom activation factory resolution test, 4 | // since activation factory resolution only happens once and is then cached. 5 | static runtimeclass ForCustomActivationFactoryResolution 6 | { 7 | static void Method(); 8 | } 9 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/IExposeObservableVector.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | // Regression test for https://github.com/tristanlabelle/swift-winrt/issues/343 4 | // where IObservableVector/IObservableMap only declare IVector/IMap and not IIterable as base interfaces, 5 | // whereas everywhere else the base interface list includes the transitive closure. 6 | // This resulted in IObservableVectorBinding.*.Import to not implement the First() method. 7 | interface IExposeObservableVector 8 | { 9 | Windows.Foundation.Collections.IObservableVector HereItIs { get; }; 10 | } 11 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/IMultiGenericInstantiation.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | // Regression test for https://github.com/tristanlabelle/swift-winrt/issues/350 4 | // where two ABI modules would contain the same generic instantiation, 5 | // resulting in a multiply defined C symbol. 6 | interface IMultiGenericInstantiation 7 | { 8 | // Force multiple instantiations of TypedEventHandler 9 | 10 | // 1. In the UWP module via IMemoryBufferReference.Closed 11 | Windows.Foundation.IMemoryBufferReference GetMemoryBufferReference(); 12 | 13 | // 2. In the WinRTComponement module via the method below 14 | Windows.Foundation.TypedEventHandler GetTypedEventHandler(); 15 | } 16 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/IMultiOutParams.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | interface IMultiOutParams 6 | { 7 | // Regression test for https://github.com/tristanlabelle/swift-winrt/issues/340 8 | // The virtual table entry for methods with multiple out params is tricky 9 | // because it requires supporting rollback if writing the second out param fails. 10 | void Get(out MinimalClass output0, out MinimalClass output1); 11 | } 12 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/InspectableBoxing.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | static runtimeclass InspectableBoxing 6 | { 7 | static IInspectable BoxInt32(Int32 value); 8 | static Int32 UnboxInt32(IInspectable value); 9 | static IInspectable BoxString(String value); 10 | static String UnboxString(IInspectable value); 11 | static IInspectable BoxMinimalEnum(MinimalEnum value); 12 | static MinimalEnum UnboxMinimalEnum(IInspectable value); 13 | static IInspectable BoxMinimalStruct(MinimalStruct value); 14 | static MinimalStruct UnboxMinimalStruct(IInspectable value); 15 | static IInspectable BoxMinimalDelegate(MinimalDelegate value); 16 | static MinimalDelegate UnboxMinimalDelegate(IInspectable value); 17 | }; 18 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/Int32Wrapper.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | runtimeclass Int32Wrapper 4 | { 5 | Int32Wrapper(); 6 | Int32 GetSet; 7 | Int32 GetOnly { get; }; 8 | }; 9 | 10 | static runtimeclass Int32Global 11 | { 12 | static Int32 GetSet; 13 | static Int32 GetOnly { get; }; 14 | }; 15 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/InterfaceCasting.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | static runtimeclass InterfaceCasting 6 | { 7 | static IMinimalInterface AsMinimalInterface(IInspectable object); 8 | } 9 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/ManualAsyncOperation.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | runtimeclass ManualAsyncOperation : Windows.Foundation.IAsyncOperation 4 | { 5 | ManualAsyncOperation(Int32 id); 6 | void Complete(Int32 result); 7 | void CompleteWithError(HRESULT errorCode); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/MinimalTypes.idl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace WinRTComponent 4 | { 5 | enum MinimalEnum 6 | { 7 | One = 1 8 | }; 9 | 10 | struct MinimalStruct 11 | { 12 | Int32 Field; 13 | }; 14 | 15 | delegate void MinimalDelegate(); 16 | 17 | interface IMinimalInterface 18 | { 19 | void Method(); 20 | } 21 | 22 | static runtimeclass MinimalInterfaceFactory 23 | { 24 | static IMinimalInterface Create(); 25 | } 26 | 27 | runtimeclass MinimalClass 28 | { 29 | MinimalClass(); 30 | void Method(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/NullValues.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | static runtimeclass NullValues 6 | { 7 | static Boolean IsObjectNull(Object value); 8 | static Boolean IsInterfaceNull(IMinimalInterface value); 9 | static Boolean IsClassNull(MinimalClass value); 10 | static Boolean IsDelegateNull(MinimalDelegate value); 11 | static Boolean IsReferenceNull(Windows.Foundation.IReference value); 12 | 13 | static Object GetNullObject(); 14 | static IMinimalInterface GetNullInterface(); 15 | static MinimalClass GetNullClass(); 16 | static MinimalDelegate GetNullDelegate(); 17 | static Windows.Foundation.IReference GetNullReference(); 18 | } 19 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/Numbers.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | static runtimeclass Numbers 4 | { 5 | static Boolean Not(Boolean value); 6 | static UInt8 IncrementUInt8(UInt8 value); 7 | static Int16 IncrementInt16(Int16 value); 8 | static UInt16 IncrementUInt16(UInt16 value); 9 | static Int32 IncrementInt32(Int32 value); 10 | static UInt32 IncrementUInt32(UInt32 value); 11 | static Int64 IncrementInt64(Int64 value); 12 | static UInt64 IncrementUInt64(UInt64 value); 13 | static Single NegateSingle(Single value); 14 | static Double NegateDouble(Double value); 15 | }; 16 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/ObjectReferencer.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | runtimeclass ObjectReferencer 4 | { 5 | ObjectReferencer(Object obj); 6 | Object Target { get; }; 7 | UInt32 CallAddRef(); 8 | UInt32 CallRelease(); 9 | void Clear(); 10 | } 11 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/OutputArgument.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | interface IOutputArgument 6 | { 7 | void Int32(Int32 value, out Int32 result); 8 | void String(String value, out String result); 9 | void Object(Object value, out Object result); 10 | void Enum(MinimalEnum value, out MinimalEnum result); 11 | void Struct(MinimalStruct value, out MinimalStruct result); 12 | void Interface(IMinimalInterface value, out IMinimalInterface result); 13 | void Class(MinimalClass value, out MinimalClass result); 14 | void Delegate(MinimalDelegate value, out MinimalDelegate result); 15 | void Array(String[] value, out String[] result); 16 | void Reference(Windows.Foundation.IReference value, out Windows.Foundation.IReference result); 17 | } 18 | 19 | static runtimeclass OutputArgument 20 | { 21 | static IOutputArgument Create(); 22 | static IOutputArgument CreateProxy(IOutputArgument inner); 23 | } 24 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/OverloadedSum.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | runtimeclass OverloadedSum 4 | { 5 | // For testing activation factory overloading 6 | OverloadedSum(); 7 | OverloadedSum(Int32 a); 8 | OverloadedSum(Int32 a, Int32 b); 9 | 10 | Int32 Result { get; }; 11 | 12 | // For testing method overloading 13 | [overload("Of")] static Int32 Of0(); 14 | [overload("Of")] static Int32 Of1(Int32 a); 15 | [overload("Of")] static Int32 Of(Int32 a, Int32 b); 16 | } 17 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/ReferenceBoxing.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | static runtimeclass ReferenceBoxing 6 | { 7 | static Windows.Foundation.IReference BoxInt32(Int32 value); 8 | static Int32 UnboxInt32(Windows.Foundation.IReference value); 9 | // Windows.Foundation.IReference is illegal: "Invalid parameter to IReference or IReferenceArray" 10 | static Windows.Foundation.IReference BoxMinimalEnum(MinimalEnum value); 11 | static MinimalEnum UnboxMinimalEnum(Windows.Foundation.IReference value); 12 | static Windows.Foundation.IReference BoxMinimalStruct(MinimalStruct value); 13 | static MinimalStruct UnboxMinimalStruct(Windows.Foundation.IReference value); 14 | }; 15 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/ReturnArgument.idl: -------------------------------------------------------------------------------- 1 | #include "MinimalTypes.idl" 2 | 3 | namespace WinRTComponent 4 | { 5 | interface IReturnArgument 6 | { 7 | Int32 Int32(Int32 value); 8 | String String(String value); 9 | Object Object(Object value); 10 | MinimalEnum Enum(MinimalEnum value); 11 | MinimalStruct Struct(MinimalStruct value); 12 | IMinimalInterface Interface(IMinimalInterface value); 13 | MinimalClass Class(MinimalClass value); 14 | MinimalDelegate Delegate(MinimalDelegate value); 15 | String[] Array(String[] value); 16 | Windows.Foundation.IReference Reference(Windows.Foundation.IReference value); 17 | } 18 | 19 | static runtimeclass ReturnArgument 20 | { 21 | static IReturnArgument Create(); 22 | static IReturnArgument CreateProxy(IReturnArgument inner); 23 | } 24 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/ShadowingConstructors.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | unsealed runtimeclass ShadowingConstructorsBase 4 | { 5 | ShadowingConstructorsBase(Int32 param); // "value" name is reserved (due to generated COM code?) 6 | }; 7 | 8 | unsealed runtimeclass ShadowingConstructorsDerived : ShadowingConstructorsBase 9 | { 10 | // Regression test for https://github.com/tristanlabelle/swift-winrt/issues/360 11 | ShadowingConstructorsDerived(); // Does not directly shadow 12 | ShadowingConstructorsDerived(Int32 param); // Shadows 13 | }; 14 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/Strings.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | static runtimeclass Strings 4 | { 5 | static String Roundtrip(String value); 6 | static Char RoundtripChar(Char value); 7 | static String FromChars(Char[] chars); 8 | static Char[] ToChars(String value); 9 | }; 10 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/Structs.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | // WinRT structs allow primitives, strings, IReferences, and other such structs. 4 | struct LeafStruct 5 | { 6 | Int32 Int32; 7 | String String; 8 | Windows.Foundation.IReference Reference; 9 | }; 10 | 11 | struct Struct 12 | { 13 | Int32 Int32; 14 | String String; 15 | Windows.Foundation.IReference Reference; 16 | LeafStruct Nested; 17 | }; 18 | 19 | static runtimeclass Structs 20 | { 21 | static Struct Make(Int32 int32, String string, Windows.Foundation.IReference reference, LeafStruct nested); 22 | 23 | static Int32 GetInt32(Struct value); 24 | static String GetString(Struct value); 25 | static Windows.Foundation.IReference GetReference(Struct value); 26 | static LeafStruct GetNested(Struct value); 27 | 28 | static void Output(Int32 int32, String string, Windows.Foundation.IReference reference, LeafStruct nested, out Struct value); 29 | 30 | static Struct ReturnRefConstArgument(ref const Struct value); 31 | }; 32 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/SwiftAttributes.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | [attributeusage(target_runtimeclass, target_enum, target_struct, target_interface, target_delegate, target_property, target_method)] 4 | [allowmultiple] 5 | attribute SwiftAttribute 6 | { 7 | String Literal; 8 | } 9 | 10 | static runtimeclass SwiftAttributes 11 | { 12 | [Swift("MainActor")] 13 | static void MainActor(); 14 | 15 | [Swift("available(swift 1)")] 16 | static void AvailableFromSwift1(); 17 | 18 | [Swift("available(swift 1)")] 19 | [Swift("discardableResult")] 20 | static Int32 AvailableFromSwift1WithDiscardableResult(); 21 | } 22 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/WeakReferencer.idl: -------------------------------------------------------------------------------- 1 | namespace WinRTComponent 2 | { 3 | runtimeclass WeakReferencer 4 | { 5 | WeakReferencer(Object target); 6 | Object Target { get; }; 7 | } 8 | } -------------------------------------------------------------------------------- /InteropTests/WinRTComponent/WinMD/WinRTComponent.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | WinRTComponent 4 | 5 | 6 | 7 | First line 8 | Second line 9 | 10 | 11 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Tristan Labelle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Support/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(Sources) -------------------------------------------------------------------------------- /Support/Readme.md: -------------------------------------------------------------------------------- 1 | Provides the infrastructure for COM and Windows Runtime projections, which generated code depends on. -------------------------------------------------------------------------------- /Support/Sources/ABIBindings/ABIBinding.swift: -------------------------------------------------------------------------------- 1 | /// Describes how to bind an ABI type to a Swift type, 2 | /// including how to convert values between the two representations. 3 | public protocol ABIBinding { 4 | // The type for the ABI representation of values. 5 | associatedtype ABIValue 6 | 7 | /// The type for the Swift representation of values. 8 | associatedtype SwiftValue 9 | 10 | /// A default ABI value that can be used to initialize variables 11 | /// and does not imply any resource allocation (release is a no-op). 12 | static var abiDefaultValue: ABIValue { get } 13 | 14 | /// Converts a value from its ABI to its Swift representation 15 | /// without releasing the original value. 16 | static func fromABI(_ value: ABIValue) -> SwiftValue 17 | 18 | /// Converts a value from its ABI to its Swift representation, 19 | /// releasing the original value. 20 | static func fromABI(consuming value: inout ABIValue) -> SwiftValue 21 | 22 | /// Converts a value from its Swift to its ABI representation. 23 | /// The resulting value should be released as its creation might have allocated resources. 24 | static func toABI(_ value: SwiftValue) throws -> ABIValue 25 | 26 | /// Releases up any allocated resources associated with the ABI representation of a value. 27 | static func release(_ value: inout ABIValue) 28 | } 29 | 30 | extension ABIBinding { 31 | public static func fromABI(consuming value: inout ABIValue) -> SwiftValue { 32 | defer { release(&value) } 33 | return fromABI(value) 34 | } 35 | 36 | public static func withABI(_ value: SwiftValue, _ closure: (ABIValue) throws -> Result) throws -> Result { 37 | var abiValue = try toABI(value) 38 | defer { release(&abiValue) } 39 | return try closure(abiValue) 40 | } 41 | } 42 | 43 | public enum ABIBindingError: Error { 44 | case unsupported(Any.Type) 45 | } -------------------------------------------------------------------------------- /Support/Sources/ABIBindings/BoolBinding.swift: -------------------------------------------------------------------------------- 1 | /// Binds the C(++) bool type to Swift's Bool type. 2 | public enum BoolBinding: PODBinding { 3 | public typealias ABIValue = CBool 4 | public typealias SwiftValue = Bool 5 | 6 | public static var abiDefaultValue: CBool { false } 7 | public static func fromABI(_ value: CBool) -> Bool { value } 8 | public static func toABI(_ value: Bool) -> CBool { value } 9 | } -------------------------------------------------------------------------------- /Support/Sources/ABIBindings/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SOURCES *.swift) 2 | add_library(ABIBindings STATIC ${SOURCES}) 3 | # Workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/26346 4 | target_include_directories(ABIBindings INTERFACE "${CMAKE_CURRENT_BINARY_DIR}") -------------------------------------------------------------------------------- /Support/Sources/ABIBindings/CStyleEnum.swift: -------------------------------------------------------------------------------- 1 | /// Protocol for Swift structs which represent C-style enums: 2 | /// backed by a fixed-width integer, and allowing for arbitrary values. 3 | public protocol CStyleEnum: RawRepresentable, Codable, Hashable, Sendable 4 | where RawValue: FixedWidthInteger { 5 | init(rawValue value: RawValue) 6 | } 7 | -------------------------------------------------------------------------------- /Support/Sources/ABIBindings/CStyleEnumBinding.swift: -------------------------------------------------------------------------------- 1 | /// Binding for an a type implementing CStyleEnum 2 | public protocol CStyleEnumBinding: CStyleEnum, PODBinding 3 | where ABIValue == RawValue, SwiftValue == Self { 4 | } 5 | 6 | extension CStyleEnumBinding { 7 | public static var abiDefaultValue: RawValue { RawValue.zero } 8 | public static func fromABI(_ value: RawValue) -> Self { Self(rawValue: value) } 9 | public static func toABI(_ value: Self) -> RawValue { value.rawValue } 10 | } 11 | -------------------------------------------------------------------------------- /Support/Sources/ABIBindings/IdentityBinding.swift: -------------------------------------------------------------------------------- 1 | /// Binds a Swift type to an identical ABI type. 2 | public protocol IdentityBinding: PODBinding where SwiftValue == ABIValue {} 3 | 4 | extension IdentityBinding { 5 | public static func toABI(_ value: SwiftValue) -> ABIValue { value } 6 | public static func fromABI(_ value: ABIValue) -> SwiftValue { value } 7 | } -------------------------------------------------------------------------------- /Support/Sources/ABIBindings/NumericBinding.swift: -------------------------------------------------------------------------------- 1 | /// Binds a C numeric type to the corresponding Swift numeric type. 2 | public enum NumericBinding: PODBinding { 3 | public typealias ABIValue = Value 4 | public typealias SwiftValue = Value 5 | 6 | public static var abiDefaultValue: ABIValue { Value.zero } 7 | public static func fromABI(_ value: Value) -> Value { value } 8 | public static func toABI(_ value: Value) -> Value { value } 9 | } -------------------------------------------------------------------------------- /Support/Sources/ABIBindings/PODBinding.swift: -------------------------------------------------------------------------------- 1 | /// A type that binds an ABI value to its corresponding Swift value, 2 | /// where the ABI representation requires no resource allocation. 3 | public protocol PODBinding: ABIBinding { 4 | static func toABI(_ value: SwiftValue) -> ABIValue // No throw version 5 | } 6 | 7 | extension PODBinding { 8 | public static func fromABI(consuming value: inout ABIValue) -> SwiftValue { fromABI(value) } 9 | public static func release(_ value: inout ABIValue) {} 10 | } -------------------------------------------------------------------------------- /Support/Sources/ABIBindings/WideCharBinding.swift: -------------------------------------------------------------------------------- 1 | /// Binds a C(++) wchar_t type to its Swift equivalent, a UTF16 code unit. 2 | public enum WideCharBinding: PODBinding { 3 | public typealias ABIValue = UInt16 4 | public typealias SwiftValue = Unicode.UTF16.CodeUnit 5 | 6 | public static var abiDefaultValue: ABIValue { 0 } 7 | public static func fromABI(_ value: UInt16) -> Unicode.UTF16.CodeUnit { value } 8 | public static func toABI(_ value: Unicode.UTF16.CodeUnit) -> UInt16 { value } 9 | } -------------------------------------------------------------------------------- /Support/Sources/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(ABIBindings) 2 | add_subdirectory(COM_ABI) 3 | add_subdirectory(COM) 4 | add_subdirectory(WindowsRuntime_ABI) 5 | add_subdirectory(WindowsRuntime) -------------------------------------------------------------------------------- /Support/Sources/COM/ABIBindings.swift: -------------------------------------------------------------------------------- 1 | @_exported import ABIBindings -------------------------------------------------------------------------------- /Support/Sources/COM/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SOURCES *.swift) 2 | add_library(COM STATIC ${SOURCES}) 3 | target_link_libraries(COM PUBLIC ABIBindings COM_ABI) 4 | # Workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/26346 5 | target_include_directories(COM INTERFACE "${CMAKE_CURRENT_BINARY_DIR}") -------------------------------------------------------------------------------- /Support/Sources/COM/COMDelegatingTearOff.swift: -------------------------------------------------------------------------------- 1 | import COM_ABI 2 | 3 | /// A COM tear-off object providing a COM virtual table for an interface implemented by the Swift owner object. 4 | public final class COMDelegatingTearOff: COMEmbedderEx { 5 | private var comEmbedding: COMEmbedding 6 | 7 | public init(owner: IUnknown, virtualTable: VirtualTablePointer) { 8 | comEmbedding = .init(virtualTable: virtualTable, owner: nil) 9 | super.init(implementer: owner) 10 | comEmbedding.initOwner(self) 11 | } 12 | 13 | public convenience init(owner: Binding.SwiftObject, binding: Binding.Type) { 14 | self.init(owner: owner as! IUnknown, virtualTable: Binding.exportedVirtualTable) 15 | } 16 | 17 | public func toCOM() -> IUnknownReference { comEmbedding.toCOM() } 18 | } -------------------------------------------------------------------------------- /Support/Sources/COM/COMEmbedderEx.swift: -------------------------------------------------------------------------------- 1 | 2 | /// Base class for Swift objects embedding COM interfaces, 3 | /// but which do not directly provide their implementation. 4 | /// 5 | /// This is a base class and not a protocol for faster upcasting. 6 | open class COMEmbedderEx { 7 | public let implementer: AnyObject 8 | 9 | // Either of self or implementer must provide the IUnknown implementation. 10 | internal var unknown: IUnknown { (self as? IUnknown) ?? (implementer as! IUnknown) } 11 | 12 | public init(implementer: IUnknown) { 13 | self.implementer = implementer 14 | } 15 | 16 | public init(implementer: AnyObject) { 17 | self.implementer = implementer 18 | assert(self is IUnknown || implementer is IUnknown) 19 | } 20 | } -------------------------------------------------------------------------------- /Support/Sources/COM/COMError+SwiftErrorInfo.swift: -------------------------------------------------------------------------------- 1 | extension COMError { 2 | /// Wraps a Swift Error object into an `IErrorInfo` to preserve it across COM boundaries. 3 | internal final class SwiftErrorInfo: COMExportBase, IErrorInfoProtocol { 4 | public let error: Error 5 | 6 | public init(error: Error) { 7 | self.error = error 8 | } 9 | 10 | public func toABI(setErrorInfo: Bool = true) -> HResult.Value { 11 | if setErrorInfo { try? COMError.setErrorInfo(self) } 12 | return hresult.value 13 | } 14 | 15 | public var hresult: HResult { (self.error as? ErrorWithHResult)?.hresult ?? HResult.fail } 16 | public var message: String { String(describing: error) } 17 | 18 | // IErrorInfo 19 | public var guid: GUID { get throws { throw COMError.fail } } 20 | public var source: String? { get throws { throw COMError.fail } } 21 | public var description: String? { self.message } 22 | public var helpFile: String? { get throws { throw COMError.fail } } 23 | public var helpContext: UInt32 { get throws { throw COMError.fail } } 24 | } 25 | } -------------------------------------------------------------------------------- /Support/Sources/COM/COMError+createErrorInfo.swift: -------------------------------------------------------------------------------- 1 | import COM_ABI 2 | 3 | extension COMError { 4 | /// Creates an instance of `ICreateErrorInfo`. 5 | public static func createErrorInfo() throws -> ICreateErrorInfo { 6 | var createErrorInfo = ICreateErrorInfoBinding.abiDefaultValue 7 | defer { ICreateErrorInfoBinding.release(&createErrorInfo) } 8 | try COMError.fromABI(SWRT_CreateErrorInfo(&createErrorInfo)) 9 | return try NullResult.unwrap(ICreateErrorInfoBinding.fromABI(createErrorInfo)) 10 | } 11 | 12 | /// Creates an instance of `IErrorInfo` with prepopulated fields. 13 | public static func createErrorInfo(guid: GUID? = nil, source: String? = nil, description: String?, 14 | helpFile: String? = nil, helpContext: UInt32? = nil) throws -> IErrorInfo { 15 | let errorInfo = try createErrorInfo() 16 | if let guid { try errorInfo.setGUID(guid) } 17 | if let source { try errorInfo.setSource(source) } 18 | if let description { try errorInfo.setDescription(description) } 19 | if let helpFile { try errorInfo.setHelpFile(helpFile) } 20 | if let helpContext { try errorInfo.setHelpContext(helpContext) } 21 | return try errorInfo.queryInterface(IErrorInfoBinding.self) 22 | } 23 | } -------------------------------------------------------------------------------- /Support/Sources/COM/COMImplements.swift: -------------------------------------------------------------------------------- 1 | import COM_ABI 2 | 3 | /// Use as a stored property of a class to allow the object to be referenced 4 | /// as a COM object exposing a given interface. 5 | public struct COMImplements: ~Copyable { 6 | private var embedding: COMEmbedding = .init(virtualTable: InterfaceBinding.exportedVirtualTable, owner: nil) 7 | 8 | public init() {} 9 | 10 | public mutating func toCOM(owner: InterfaceBinding.SwiftObject) -> InterfaceBinding.ABIReference { 11 | // The owner should conform to IUnknownProtocol and hence be an AnyObject, 12 | // but this cannot be expressed in the type system. 13 | toCOM(owner: owner as! IUnknown) 14 | } 15 | 16 | internal mutating func toCOM(owner: IUnknown) -> InterfaceBinding.ABIReference { 17 | embedding.initOwner(owner) 18 | return embedding.toCOM().cast() 19 | } 20 | } -------------------------------------------------------------------------------- /Support/Sources/COM/COMImport.swift: -------------------------------------------------------------------------------- 1 | import COM_ABI 2 | 3 | // Base class for COM objects projected into Swift. 4 | open class COMImport: IUnknownProtocol { 5 | /// A reference to the underlying COM object. 6 | public let _reference: Binding.ABIReference 7 | 8 | /// A pointer to the underlying COM object. 9 | public var _pointer: UnsafeMutablePointer { _reference.pointer } 10 | 11 | /// The interop wrapper for the underlying COM object. 12 | public var _interop: COMInterop { _reference.interop } 13 | 14 | /// Initializes a new instance from a COM object reference. 15 | public required init(_wrapping reference: consuming Binding.ABIReference) { 16 | self._reference = reference 17 | } 18 | 19 | public func _queryInterface(_ id: COMInterfaceID) throws -> IUnknownReference { 20 | try _reference.interop.queryInterface(id) 21 | } 22 | 23 | // COMBinding implementation helpers 24 | open class func toCOM(_ object: Binding.SwiftObject) throws -> Binding.ABIReference { 25 | switch object { 26 | // If this is already a wrapped COM object, return the wrapped object 27 | case let comImport as Self: return comImport._reference.clone() 28 | // Otherwise ask the object to project itself to a COM object 29 | case let unknown as COM.IUnknown: return try unknown._queryInterface(Binding.self) 30 | default: throw ABIBindingError.unsupported(Binding.SwiftObject.self) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Support/Sources/COM/COMReference+Optional.swift: -------------------------------------------------------------------------------- 1 | extension COMReference { 2 | /// Smart pointer-like reference to a COM object or to nil. 3 | /// Essentially an Optional without language support. 4 | public struct Optional: ~Copyable { 5 | public static var none: Self { Self() } 6 | 7 | private var pointer: UnsafeMutablePointer? 8 | 9 | public init() { 10 | self.pointer = nil 11 | } 12 | 13 | public init(_ reference: consuming COMReference) { 14 | self.pointer = reference.detach() 15 | } 16 | 17 | public mutating func detach() -> UnsafeMutablePointer? { 18 | defer { pointer = nil } 19 | return pointer 20 | } 21 | 22 | public consuming func finalDetach() -> UnsafeMutablePointer? { 23 | let pointer = self.pointer 24 | discard self 25 | return pointer 26 | } 27 | 28 | public mutating func lazyInitPointer(_ factory: () throws -> COMReference) rethrows -> UnsafeMutablePointer { 29 | if let pointer { return pointer } 30 | let new = try factory().detach() 31 | self.pointer = new 32 | return new 33 | } 34 | 35 | public mutating func lazyInitInterop(_ factory: () throws -> COMReference) rethrows -> COMInterop { 36 | try COMInterop(lazyInitPointer(factory)) 37 | } 38 | 39 | deinit { 40 | if let pointer { 41 | COMInterop(pointer).release() 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Support/Sources/COM/COMReference.swift: -------------------------------------------------------------------------------- 1 | import COM_ABI 2 | 3 | /// Holds a strong reference to a COM object, releasing it when deinitialized, like a C++ smart pointer. 4 | public struct COMReference: ~Copyable { 5 | public var pointer: UnsafeMutablePointer 6 | 7 | public init(transferringRef pointer: UnsafeMutablePointer) { 8 | self.pointer = pointer 9 | } 10 | 11 | public init(addingRef pointer: UnsafeMutablePointer) { 12 | self.init(transferringRef: pointer) 13 | interop.addRef() 14 | } 15 | 16 | public var interop: COMInterop { .init(pointer) } 17 | 18 | public func clone() -> COMReference { .init(addingRef: pointer) } 19 | 20 | public consuming func detach() -> UnsafeMutablePointer { 21 | let pointer = self.pointer 22 | discard self 23 | return pointer 24 | } 25 | 26 | public func queryInterface(_ id: COMInterfaceID) throws -> IUnknownReference { 27 | try interop.queryInterface(id) 28 | } 29 | 30 | public func queryInterface( 31 | _ id: COMInterfaceID, type: OtherABIStruct.Type = OtherABIStruct.self) throws -> COMReference { 32 | try interop.queryInterface(id, type: type) 33 | } 34 | 35 | public consuming func cast( 36 | to type: OtherABIStruct.Type = OtherABIStruct.self) -> COMReference { 37 | let pointer = self.pointer 38 | discard self 39 | return COMReference(transferringRef: pointer.withMemoryRebound(to: OtherABIStruct.self, capacity: 1) { $0 }) 40 | } 41 | 42 | deinit { 43 | interop.release() 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Support/Sources/COM/COMTearOffBase.swift: -------------------------------------------------------------------------------- 1 | /// A COM-exported object providing a secondary interface to a primary exported object. 2 | open class COMTearOffBase: IUnknownProtocol { 3 | private var implements: COMImplements = .init() 4 | public let owner: IUnknown 5 | 6 | public init(owner: IUnknown) { 7 | self.owner = owner 8 | } 9 | 10 | public func toCOM() -> InterfaceBinding.ABIReference { 11 | implements.toCOM(owner: self) 12 | } 13 | 14 | open func _queryInterface(_ id: COMInterfaceID) throws -> IUnknownReference { 15 | switch id { 16 | case InterfaceBinding.interfaceID: return toCOM().cast() 17 | default: return try owner._queryInterface(id) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Support/Sources/COM/COMTwoWayBinding.swift: -------------------------------------------------------------------------------- 1 | import COM_ABI 2 | 3 | /// Protocol for COM interfaces projected into Swift both for consuming COM objects 4 | /// and for implementing the interface from Swift. 5 | public protocol COMTwoWayBinding: COMBinding { 6 | /// A pointer to a virtual table which implements the COM interface via a Swift object. 7 | static var exportedVirtualTable: VirtualTablePointer { get } 8 | } 9 | 10 | extension COMTwoWayBinding { 11 | public static func _unwrap(_ pointer: ABIPointer) -> SwiftObject? { 12 | COMEmbedding.getImplementer(pointer) 13 | } 14 | 15 | /// Helper for implementing virtual tables 16 | public static func _implement(_ this: UnsafeMutablePointer?, _ body: (SwiftObject) throws -> Void) -> COM_ABI.SWRT_HResult { 17 | guard let this else { return COMError.toABI(hresult: HResult.pointer, description: "COM 'this' pointer was null") } 18 | let implementation: SwiftObject = COMEmbedding.getImplementerUnsafe(this) 19 | return COMError.toABI { try body(implementation) } 20 | } 21 | 22 | public static func _set( 23 | _ pointer: UnsafeMutablePointer?, 24 | _ value: @autoclosure () throws -> Value) throws { 25 | guard let pointer else { throw COMError.pointer } 26 | pointer.pointee = try value() 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Support/Sources/COM/Projection/BStrBinding.swift: -------------------------------------------------------------------------------- 1 | import COM_ABI 2 | 3 | /// Binds a C BSTR to a Swift Optional. 4 | /// Null and empty BSTRs are supposed to be treated the same, 5 | /// but they have different representations, which we preserve into Swift. 6 | public enum BStrBinding: ABIBinding { 7 | public typealias SwiftValue = String? 8 | public typealias ABIValue = COM_ABI.SWRT_BStr? 9 | 10 | public static var abiDefaultValue: ABIValue { nil } 11 | 12 | public static func fromABI(_ value: COM_ABI.SWRT_BStr?) -> String? { 13 | guard let value else { return nil } 14 | let length = COM_ABI.SWRT_SysStringLen(value) 15 | return String(utf16CodeUnits: value, count: Int(length)) 16 | } 17 | 18 | public static func toABI(_ value: String?) throws -> COM_ABI.SWRT_BStr? { 19 | guard let value else { return nil } 20 | return value.withCString(encodedAs: UTF16.self) { pointer in 21 | COM_ABI.SWRT_SysAllocString(pointer) 22 | } 23 | } 24 | 25 | public static func release(_ value: inout COM_ABI.SWRT_BStr?) { 26 | // Docs: "If this parameter is NULL, the function simply returns." 27 | COM_ABI.SWRT_SysFreeString(value) 28 | value = nil 29 | } 30 | } -------------------------------------------------------------------------------- /Support/Sources/COM/Projection/HResult+getMessage.swift: -------------------------------------------------------------------------------- 1 | import WinSDK 2 | 3 | extension HResult { 4 | public static func getMessage(_ hr: Value) -> String? { 5 | let dwFlags: WinSDK.DWORD = WinSDK.DWORD(WinSDK.FORMAT_MESSAGE_ALLOCATE_BUFFER) 6 | | WinSDK.DWORD(WinSDK.FORMAT_MESSAGE_FROM_SYSTEM) 7 | | WinSDK.DWORD(WinSDK.FORMAT_MESSAGE_IGNORE_INSERTS) 8 | 9 | var buffer: UnsafeMutablePointer? = nil 10 | // When specifying ALLOCATE_BUFFER, lpBuffer is used as an LPWSTR* 11 | let dwResult: WinSDK.DWORD = withUnsafeMutablePointer(to: &buffer) { 12 | $0.withMemoryRebound(to: WCHAR.self, capacity: 1) { 13 | WinSDK.FormatMessageW( 14 | dwFlags, 15 | /* lpSource: */ nil, 16 | /* dwMessageId: */ WinSDK.DWORD(bitPattern: hr), 17 | /* dwLanguageId: */ 0, 18 | /* lpBuffer*/ $0, 19 | /* nSize: */ 0, 20 | /* Arguments: */ nil) 21 | } 22 | } 23 | guard let buffer else { return nil } 24 | defer { WinSDK.LocalFree(buffer) } 25 | guard dwResult > 0 else { return nil } 26 | 27 | var message = String(decodingCString: buffer, as: UTF16.self) 28 | // Remove any trailing whitespaces 29 | while let lastIndex = message.indices.last, message[lastIndex].isWhitespace { 30 | message.remove(at: lastIndex) 31 | } 32 | return message 33 | } 34 | } -------------------------------------------------------------------------------- /Support/Sources/COM/Projection/HResult.swift: -------------------------------------------------------------------------------- 1 | import COM_ABI 2 | 3 | /// Represents a COM HRESULT value in Swift. 4 | public struct HResult: Hashable, Codable, CustomStringConvertible, Sendable { 5 | public typealias Value = Int32 6 | public typealias UnsignedValue = UInt32 7 | 8 | public static let ok = HResult(0) 9 | public static let illegalMethodCall = HResult(unsigned: 0x8000000E) 10 | public static let fail = HResult(unsigned: 0x80004005) 11 | public static let invalidArg = HResult(unsigned: 0x80070057) 12 | public static let notImpl = HResult(unsigned: 0x80004001) 13 | public static let noInterface = HResult(unsigned: 0x80004002) 14 | public static let pointer = HResult(unsigned: 0x80004003) 15 | public static let outOfMemory = HResult(unsigned: 0x8007000E) 16 | 17 | public var value: Value 18 | public var unsignedValue: UnsignedValue { UnsignedValue(bitPattern: value) } 19 | 20 | public init(_ value: Value) { self.value = value } 21 | public init(unsigned: UnsignedValue) { self.value = Value(bitPattern: unsigned) } 22 | 23 | public var isSuccess: Bool { Self.isSuccess(value) } 24 | public var isFailure: Bool { Self.isFailure(value) } 25 | 26 | public var message: String? { Self.getMessage(value) } 27 | 28 | public var hexValue: String { 29 | let prepaddedValue = UInt64(unsignedValue) | (UInt64(0xFF) << 32) 30 | var result = String(prepaddedValue, radix: 16, uppercase: true) 31 | result.replaceSubrange(result.firstRange(of: "FF")!, with: "0x") 32 | return result 33 | } 34 | 35 | public var description: String { 36 | if let message = self.message { 37 | return "HRESULT(\(hexValue)): \(message)" 38 | } 39 | 40 | return "HRESULT(\(hexValue))" 41 | } 42 | 43 | public static func isSuccess(_ hr: Value) -> Bool { hr >= 0 } 44 | public static func isFailure(_ hr: Value) -> Bool { hr < 0 } 45 | } -------------------------------------------------------------------------------- /Support/Sources/COM/Projection/HResultBinding.swift: -------------------------------------------------------------------------------- 1 | import COM_ABI 2 | 3 | public enum HResultBinding: PODBinding { 4 | public typealias SwiftValue = HResult 5 | public typealias ABIValue = COM_ABI.SWRT_HResult 6 | 7 | public static var abiDefaultValue: ABIValue { 0 /* S_OK */ } 8 | public static func fromABI(_ value: COM_ABI.SWRT_HResult) -> SwiftValue { HResult(value) } 9 | public static func toABI(_ value: HResult) -> COM_ABI.SWRT_HResult { value.value } 10 | } -------------------------------------------------------------------------------- /Support/Sources/COM/Projection/IAgileObject.swift: -------------------------------------------------------------------------------- 1 | import COM_ABI 2 | 3 | /// Binding for the IAgileObject COM interface, which marks an object as supporting agile marshaling. 4 | /// IAgileObject is a marker interface with no methods over IUnknown's, so it does not need its own virtual table. 5 | /// This means we can piggyback on the IUnknown virtual table to transparently implement IAgileObject, 6 | /// so we don't need to expose a protocol type for it or a two-way binding. 7 | public enum IAgileObjectBinding: COMBinding { 8 | public typealias SwiftObject = IUnknown // Avoid introducing an interface for IAgileObject since it is a marker interface. 9 | public typealias ABIStruct = COM_ABI.SWRT_IAgileObject 10 | 11 | public static var interfaceID: COMInterfaceID { uuidof(ABIStruct.self) } 12 | 13 | public static func _wrap(_ reference: consuming ABIReference) -> SwiftObject { 14 | IUnknownBinding._wrap(reference.cast()) 15 | } 16 | 17 | public static func toCOM(_ object: SwiftObject) throws -> ABIReference { 18 | try object._queryInterface(Self.self) 19 | } 20 | } 21 | 22 | public func uuidof(_: COM_ABI.SWRT_IAgileObject.Type) -> COMInterfaceID { 23 | .init(0x94EA2B94, 0xE9CC, 0x49E0, 0xC0FF, 0xEE64CA8F5B90) 24 | } -------------------------------------------------------------------------------- /Support/Sources/COM/SupportErrorInfoForAllInterfaces.swift: -------------------------------------------------------------------------------- 1 | /// An implementation of ISupportErrorInfo which reports that all interfaces support error info. 2 | public final class SupportErrorInfoForAllInterfaces: COMTearOffBase, ISupportErrorInfoProtocol { 3 | public func interfaceSupportsErrorInfo(_ riid: COMInterfaceID) throws { 4 | // Never throw. By virtue of projection, all interfaces report their errors through IErrorInfo. 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Support/Sources/COM/VirtualTablePointer.swift: -------------------------------------------------------------------------------- 1 | public typealias VirtualTablePointer = UnsafeRawPointer -------------------------------------------------------------------------------- /Support/Sources/COM/comIdentical.swift: -------------------------------------------------------------------------------- 1 | public func comIdentical(_ lhs: IUnknown, _ rhs: IUnknown) -> Bool { 2 | guard let lhsIdentityReference = try? lhs._queryInterface(IUnknownBinding.interfaceID) else { return false } 3 | guard let rhsIdentityReference = try? rhs._queryInterface(IUnknownBinding.interfaceID) else { return false } 4 | return lhsIdentityReference.pointer == rhsIdentityReference.pointer 5 | } -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB SOURCES *.c) 2 | add_library(COM_ABI STATIC ${SOURCES}) 3 | target_include_directories(COM_ABI PUBLIC include) -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/combaseapi.c: -------------------------------------------------------------------------------- 1 | #include "SWRT/winapi/combaseapi.h" 2 | 3 | #include 4 | #include 5 | 6 | SWRT_HResult SWRT_CoCreateFreeThreadedMarshaler(SWRT_IUnknown* punkOuter, SWRT_IUnknown** ppunkMarshal) { 7 | return (SWRT_HResult)CoCreateFreeThreadedMarshaler((IUnknown*)punkOuter, (IUnknown**)ppunkMarshal); 8 | } -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/include/SWRT/COMEmbedding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define SWRT_COMEmbedding_OwnerFlags_Mask ((uintptr_t)1) 6 | /// The owner object derives from COMEmbedderEx. 7 | #define SWRT_COMEmbedding_OwnerFlags_Extended ((uintptr_t)1) 8 | 9 | /// Allows Swift objects to expose a COM interface to COM clients. 10 | /// This structure is embedded in a Swift reference-counted object, 11 | /// where its pointer can be treated as a an ABI-compatible COM object 12 | /// derived from IUnknown. 13 | typedef struct SWRT_COMEmbedding { 14 | /// The IUnknown-based virtual table for the COM object. 15 | const void* virtualTable; 16 | 17 | /// A tagged Unmanaged pointer to the Swift object that 18 | /// controls the lifetime of this structure, directly or indirectly. 19 | /// This object is retained and released by AddRef/Release calls. 20 | /// The least significant bits store SWRT_COMEmbeddingFlags. 21 | uintptr_t swiftOwnerAndFlags; 22 | } SWRT_COMEmbedding; 23 | -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/include/SWRT/modules/COM.h: -------------------------------------------------------------------------------- 1 | #include "SWRT/winapi/BaseTsd.h" 2 | #include "SWRT/winapi/combaseapi.h" 3 | #include "SWRT/winapi/guiddef.h" 4 | #include "SWRT/winapi/oaidl.h" 5 | #include "SWRT/winapi/objidl.h" 6 | #include "SWRT/winapi/oleauto.h" 7 | #include "SWRT/winapi/unknwn.h" -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/include/SWRT/winapi/BaseTsd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef int32_t SWRT_HResult; -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/include/SWRT/winapi/combaseapi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/BaseTsd.h" 4 | #include "SWRT/winapi/unknwn.h" 5 | 6 | SWRT_HResult SWRT_CoCreateFreeThreadedMarshaler(SWRT_IUnknown* punkOuter, SWRT_IUnknown** ppunkMarshal); -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/include/SWRT/winapi/guiddef.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // GUID 6 | typedef struct SWRT_Guid { 7 | uint32_t Data1; 8 | uint16_t Data2; 9 | uint16_t Data3; 10 | uint8_t Data4[8]; 11 | } SWRT_Guid; -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/include/SWRT/winapi/objidl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/guiddef.h" 4 | #include "SWRT/winapi/oleauto.h" 5 | #include "SWRT/winapi/unknwn.h" 6 | 7 | // IAgileObject 8 | typedef struct SWRT_IAgileObject { 9 | struct SWRT_IAgileObject_VirtualTable* VirtualTable; 10 | } SWRT_IAgileObject; 11 | 12 | struct SWRT_IAgileObject_VirtualTable { 13 | SWRT_HResult (__stdcall *QueryInterface)(SWRT_IAgileObject* _this, SWRT_Guid* riid, void** ppvObject); 14 | uint32_t (__stdcall *AddRef)(SWRT_IAgileObject* _this); 15 | uint32_t (__stdcall *Release)(SWRT_IAgileObject* _this); 16 | }; 17 | 18 | // IStream 19 | typedef struct SWRT_IStream SWRT_IStream; 20 | 21 | // IMarshal 22 | typedef struct SWRT_IMarshal { 23 | struct SWRT_IMarshal_VirtualTable* VirtualTable; 24 | } SWRT_IMarshal; 25 | 26 | struct SWRT_IMarshal_VirtualTable { 27 | SWRT_HResult (__stdcall *QueryInterface)(SWRT_IMarshal* _this, SWRT_Guid* riid, void** ppvObject); 28 | uint32_t (__stdcall *AddRef)(SWRT_IMarshal* _this); 29 | uint32_t (__stdcall *Release)(SWRT_IMarshal* _this); 30 | SWRT_HResult (__stdcall *GetUnmarshalClass)(SWRT_IMarshal *_this, SWRT_Guid* riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, SWRT_Guid* pCid); 31 | SWRT_HResult (__stdcall *GetMarshalSizeMax)(SWRT_IMarshal *_this, SWRT_Guid* riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, uint32_t* pSize); 32 | SWRT_HResult (__stdcall *MarshalInterface)(SWRT_IMarshal *_this, SWRT_IStream* pStm, SWRT_Guid* riid, void *pv, uint32_t dwDestContext, void *pvDestContext, uint32_t mshlflags); 33 | SWRT_HResult (__stdcall *UnmarshalInterface)(SWRT_IMarshal *_this, SWRT_IStream* pStm, SWRT_Guid* riid, void **ppv); 34 | SWRT_HResult (__stdcall *ReleaseMarshalData)(SWRT_IMarshal *_this, SWRT_IStream* pStm); 35 | SWRT_HResult (__stdcall *DisconnectObject)(SWRT_IMarshal *_this, uint32_t dwReserved); 36 | }; -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/include/SWRT/winapi/oleauto.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "SWRT/winapi/wtypes.h" 5 | #include "SWRT/winapi/oaidl.h" 6 | 7 | SWRT_HResult SWRT_CreateErrorInfo(SWRT_ICreateErrorInfo ** pperrinfo); 8 | SWRT_HResult SWRT_GetErrorInfo(uint32_t dwReserved, SWRT_IErrorInfo** pperrinfo); 9 | SWRT_HResult SWRT_SetErrorInfo(uint32_t dwReserved, SWRT_IErrorInfo* perrinfo); 10 | SWRT_BStr SWRT_SysAllocString(const char16_t* strIn); 11 | SWRT_BStr SWRT_SysAllocStringLen(const char16_t* strIn, uint32_t ui); 12 | void SWRT_SysFreeString(SWRT_BStr bstrString); 13 | uint32_t SWRT_SysStringLen(SWRT_BStr pbstr); -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/include/SWRT/winapi/unknwn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/guiddef.h" 4 | #include "SWRT/winapi/BaseTsd.h" 5 | 6 | // IUnknown 7 | typedef struct SWRT_IUnknown { 8 | struct SWRT_IUnknown_VirtualTable* VirtualTable; 9 | } SWRT_IUnknown; 10 | 11 | struct SWRT_IUnknown_VirtualTable { 12 | SWRT_HResult (__stdcall *QueryInterface)(SWRT_IUnknown* _this, SWRT_Guid* riid, void** ppvObject); 13 | uint32_t (__stdcall *AddRef)(SWRT_IUnknown* _this); 14 | uint32_t (__stdcall *Release)(SWRT_IUnknown* _this); 15 | }; 16 | -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/include/SWRT/winapi/wtypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef char16_t* SWRT_BStr; -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/include/module.modulemap: -------------------------------------------------------------------------------- 1 | module COM_ABI { 2 | header "SWRT/modules/COM.h" 3 | header "SWRT/winapi/BaseTsd.h" 4 | header "SWRT/winapi/combaseapi.h" 5 | header "SWRT/winapi/guiddef.h" 6 | header "SWRT/winapi/oaidl.h" 7 | header "SWRT/winapi/objidl.h" 8 | header "SWRT/winapi/oleauto.h" 9 | header "SWRT/winapi/unknwn.h" 10 | header "SWRT/winapi/wtypes.h" 11 | header "SWRT/COMEmbedding.h" 12 | export * 13 | } 14 | 15 | module COM_PrivateABI { 16 | header "SWRT/COMEmbedding.h" 17 | export * 18 | } -------------------------------------------------------------------------------- /Support/Sources/COM_ABI/oleauto.c: -------------------------------------------------------------------------------- 1 | #include "SWRT/winapi/oleauto.h" 2 | 3 | #include 4 | #include 5 | 6 | SWRT_HResult SWRT_CreateErrorInfo(SWRT_ICreateErrorInfo ** pperrinfo) { 7 | return (SWRT_HResult)CreateErrorInfo((ICreateErrorInfo**)pperrinfo); 8 | } 9 | 10 | SWRT_HResult SWRT_GetErrorInfo(uint32_t dwReserved, SWRT_IErrorInfo** pperrinfo) { 11 | return (SWRT_HResult)GetErrorInfo(dwReserved, (IErrorInfo**)pperrinfo); 12 | } 13 | 14 | SWRT_HResult SWRT_SetErrorInfo(uint32_t dwReserved, SWRT_IErrorInfo* perrinfo) { 15 | return (SWRT_HResult)SetErrorInfo(dwReserved, (IErrorInfo*)perrinfo); 16 | } 17 | 18 | SWRT_BStr SWRT_SysAllocString(const char16_t* strIn) { 19 | return (SWRT_BStr)SysAllocString((const OLECHAR*)strIn); 20 | } 21 | 22 | SWRT_BStr SWRT_SysAllocStringLen(const char16_t* strIn, uint32_t ui) { 23 | return (SWRT_BStr)SysAllocStringLen((const OLECHAR*)strIn, (UINT)ui); 24 | } 25 | 26 | void SWRT_SysFreeString(SWRT_BStr bstrString) { 27 | SysFreeString((BSTR)bstrString); 28 | } 29 | 30 | uint32_t SWRT_SysStringLen(SWRT_BStr pbstr) { 31 | return (uint32_t)SysStringLen((BSTR)pbstr); 32 | } -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/AsyncAwaiter.swift: -------------------------------------------------------------------------------- 1 | /// Supports converting an async callback pattern into a form compatible with Swift's await. 2 | /// Used to support `IAsyncAction.get`/`IAsyncOperation.get`. 3 | public actor AsyncAwaiter { 4 | private enum State { 5 | case unsignaled 6 | case awaitingSignal(continuation: CheckedContinuation) 7 | case signaled 8 | } 9 | 10 | private var state: State = .unsignaled 11 | 12 | public init() {} 13 | 14 | /// Block until `signal()` has been called. 15 | public func wait() async { 16 | switch state { 17 | case .signaled: return 18 | case .awaitingSignal: fatalError("Reentrant wait() call") 19 | case .unsignaled: 20 | await withCheckedContinuation { state = .awaitingSignal(continuation: $0) } 21 | } 22 | } 23 | 24 | /// Unblocks any current or future `wait()` calls. 25 | public func signal() async { 26 | switch state { 27 | case .unsignaled: state = .signaled 28 | case .awaitingSignal(let continuation): 29 | state = .signaled 30 | continuation.resume() 31 | case .signaled: break 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE SOURCES *.swift) 2 | add_library(WindowsRuntime STATIC ${SOURCES}) 3 | target_link_libraries(WindowsRuntime PUBLIC COM WindowsRuntime_ABI) 4 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/ClosedEnum.swift: -------------------------------------------------------------------------------- 1 | /// Protocol for Swift enums which represent WinRT enums but do not allow arbitrary values. 2 | public protocol ClosedEnum: RawRepresentable, Codable, Hashable, Sendable 3 | where RawValue: FixedWidthInteger {} -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/EventRegistration.swift: -------------------------------------------------------------------------------- 1 | /// Represents a registration of an event handler with an event source and supports removing the registration. 2 | public struct EventRegistration { 3 | // We store and pass in the event source object so removal closures do not need to capture context, avoiding allocations. 4 | public typealias Remover = (_ source: AnyObject, _ token: EventRegistrationToken) throws -> Void 5 | 6 | /// The object that is the source of the event. 7 | private var source: AnyObject 8 | /// The token that represents the event registration. 9 | public private(set) var token: EventRegistrationToken 10 | /// The closure that removes the event registration. 11 | private var remover: Remover 12 | 13 | public init(source: AnyObject, token: EventRegistrationToken, remover: @escaping Remover) { 14 | self.source = source 15 | self.token = token 16 | self.remover = remover 17 | } 18 | 19 | public mutating func detachToken() -> EventRegistrationToken { 20 | remover = Self.nullRemover 21 | defer { token = .none } 22 | return token 23 | } 24 | 25 | public mutating func remove() throws { 26 | try remover(source, token) 27 | token = .none 28 | remover = Self.nullRemover 29 | } 30 | 31 | private static let nullRemover: Remover = { _, _ in } 32 | } -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/ExportedDelegate.swift: -------------------------------------------------------------------------------- 1 | import COM 2 | 3 | /// A COM-exported object delegating its implementation to a Swift object. 4 | public final class ExportedDelegate: COMEmbedderEx, IUnknownProtocol { 5 | private var comEmbedding: COMEmbedding 6 | 7 | public init(_ closure: Binding.SwiftObject) { 8 | self.comEmbedding = .init(virtualTable: Binding.exportedVirtualTable, owner: nil) 9 | super.init(implementer: closure as AnyObject) 10 | self.comEmbedding.initOwner(self as COMEmbedderEx) 11 | } 12 | 13 | public func toCOM() -> Binding.ABIReference { 14 | comEmbedding.toCOM().cast() 15 | } 16 | 17 | public func _queryInterface(_ id: COMInterfaceID) throws -> IUnknownReference { 18 | switch id { 19 | // Delegates are always agile and free-threaded. 20 | case Binding.interfaceID, IUnknownBinding.interfaceID, IAgileObjectBinding.interfaceID: 21 | return toCOM().cast() 22 | case FreeThreadedMarshalBinding.interfaceID: 23 | return try FreeThreadedMarshal(self).toCOM().cast() 24 | case ISupportErrorInfoBinding.interfaceID: 25 | return SupportErrorInfoForAllInterfaces(owner: self).toCOM().cast() 26 | default: 27 | throw COMError.noInterface 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/IReferenceToOptionalBinding.swift: -------------------------------------------------------------------------------- 1 | import COM 2 | import WindowsRuntime_ABI 3 | import SWRT_WindowsFoundation 4 | 5 | /// Binds IReference? to T? for boxable T's like primitive types, values types and delegates. 6 | public enum IReferenceToOptionalBinding: WinRTBinding, COMBinding { 7 | public typealias SwiftObject = Binding.SwiftValue 8 | public typealias ABIStruct = SWRT_WindowsFoundation_IReference 9 | 10 | public static var typeName: Swift.String { "Windows.Foundation.IReference`1<\(Binding.typeName)>" } 11 | public static var interfaceID: COMInterfaceID { Binding.ireferenceID } 12 | 13 | // Value types have no identity, so there's no sense unwrapping them. 14 | public static func _wrap(_ reference: consuming ABIReference) -> SwiftObject { 15 | var abiValue = Binding.abiDefaultValue 16 | withUnsafeMutablePointer(to: &abiValue) { abiValuePointer in 17 | try! reference.interop.get_Value(abiValuePointer) 18 | } 19 | return Binding.fromABI(consuming: &abiValue) 20 | } 21 | 22 | public static func toCOM(_ value: SwiftObject) throws -> ABIReference { 23 | try Binding.createIReference(value)._queryInterface(interfaceID) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/ModuleReexports.swift: -------------------------------------------------------------------------------- 1 | @_exported import COM -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/Projection/Char16.swift: -------------------------------------------------------------------------------- 1 | /// Represents the WinRT Char16 (aka System.Char) type, a UTF-16 code unit. 2 | /// Supports type-based disambiguation from UInt16 values. 3 | public struct Char16: Hashable, Codable, Sendable { 4 | public var codeUnit: UTF16.CodeUnit 5 | 6 | public init(_ codeUnit: UTF16.CodeUnit) { 7 | self.codeUnit = codeUnit 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/Projection/EventRegistrationToken.swift: -------------------------------------------------------------------------------- 1 | import COM 2 | import WindowsRuntime_ABI 3 | 4 | public struct EventRegistrationToken: Hashable, Sendable { 5 | public var value: Int64 6 | public init(_ value: Int64 = 0) { self.value = value } 7 | 8 | public static let none = Self(0) 9 | } 10 | 11 | extension EventRegistrationToken: PODBinding { 12 | public typealias SwiftValue = Self 13 | public typealias ABIValue = WindowsRuntime_ABI.SWRT_EventRegistrationToken 14 | 15 | public static var abiDefaultValue: ABIValue { WindowsRuntime_ABI.SWRT_EventRegistrationToken(value: 0) } 16 | public static func fromABI(_ value: ABIValue) -> SwiftValue { SwiftValue(value.value) } 17 | public static func toABI(_ value: SwiftValue) -> ABIValue { ABIValue(value: value.value) } 18 | } -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/Projection/Readme.md: -------------------------------------------------------------------------------- 1 | Defines Swift projections for core WinRT types, and COM types that support the Windows Runtime. Those types are defined in native idl or C++ headers rather than Windows Metadata files and cannot be generated. -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/Projection/TrustLevel.swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime_ABI 2 | import COM 3 | 4 | /// Represents the trust level of an activatable class. 5 | public struct TrustLevel: CStyleEnum { 6 | public var rawValue: Int32 7 | public init(rawValue: Int32 = 0) { self.rawValue = rawValue } 8 | 9 | /// The component has access to resources that are not protected. 10 | public static let base = Self(rawValue: 0) 11 | 12 | /// The component has access to resources requested in the app manifest and approved by the user. 13 | public static let partial = Self(rawValue: 1) 14 | 15 | /// The component requires the full privileges of the user. 16 | public static let full = Self(rawValue: 2) 17 | } 18 | 19 | extension TrustLevel: CStyleEnumBinding {} -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/Projection/WindowsFoundation/Readme.md: -------------------------------------------------------------------------------- 1 | This directory defines core types from the `Windows.Foundation` namespace (`Windows.Foundation.WindowsFoundationContract` assembly), 2 | which are required by WinRT support code and hence cannot be code generated. 3 | 4 | `IReference` and `IReferenceArray` need built-in support because we can express them through a single virtual table, independent of T, which allows implementing boxing for arbitrary primitive types, value types and delegate types. 5 | 6 | `IPropertyValue` and `PropertyType` have nothing special and could be code generated, if it were not that the former is a base interface for `IReference` and `IReferenceArray`. `IPropertyValue` also refers to `DateTime`/`TimeSpan` and `Point`/`Size`/`Rect`, preventing them from being code generated. 7 | 8 | `IStringable` has built-in support so we can automatically implement it in terms of `CustomStringConvertible`. -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/ReferenceArrayImpl.swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime_ABI 2 | 3 | /// Implements IReferenceArray for any boxable T not provided by the UWP PropertyValue class (value types and delegates). 4 | internal class ReferenceArrayImpl 5 | : WinRTExportBase>, 6 | WindowsFoundation_IReferenceArrayProtocol { 7 | public typealias T = TBinding.SwiftValue 8 | 9 | public override class var _runtimeClassName: String { "Windows.Foundation.IReferenceArray`1<\(TBinding.typeName)>" } 10 | 11 | private let _value: [TBinding.SwiftValue] 12 | 13 | init(_ value: [TBinding.SwiftValue]) { 14 | self._value = value 15 | super.init() 16 | } 17 | 18 | // IPropertyValue members 19 | public var type: WindowsFoundation_PropertyType { get throws { .otherTypeArray } } 20 | public var isNumericScalar: Bool { get throws { false } } 21 | 22 | public var value: [T] { get throws { _value } } 23 | 24 | public func _getABIValue(_ length: inout UInt32, _ pointer: inout UnsafeMutableRawPointer?) throws { 25 | let abiValue = try ArrayBinding.toABI(self._value) 26 | length = abiValue.count 27 | pointer = abiValue.pointer.map { UnsafeMutableRawPointer($0) } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/ReferenceImpl.swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime_ABI 2 | 3 | /// Implements IReference for any boxable T not provided by the UWP PropertyValue class (value types and delegates). 4 | internal class ReferenceImpl 5 | : WinRTExportBase>, 6 | WindowsFoundation_IReferenceProtocol { 7 | public typealias T = TBinding.SwiftValue 8 | 9 | public override class var _runtimeClassName: String { "Windows.Foundation.IReference`1<\(TBinding.typeName)>" } 10 | 11 | private let _value: TBinding.SwiftValue 12 | 13 | init(_ value: TBinding.SwiftValue) { 14 | self._value = value 15 | super.init() 16 | } 17 | 18 | // IPropertyValue members 19 | public var type: WindowsFoundation_PropertyType { get throws { .otherType } } 20 | public var isNumericScalar: Bool { get throws { false } } 21 | public var value: T { get throws { _value } } 22 | 23 | public func _getABIValue(_ pointer: UnsafeMutableRawPointer) throws { 24 | pointer.bindMemory(to: TBinding.ABIValue.self, capacity: 1).pointee = try TBinding.toABI(_value) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/SwiftWrapperFactory.swift: -------------------------------------------------------------------------------- 1 | public protocol SwiftWrapperFactory { 2 | func create( 3 | _ reference: consuming StaticBinding.ABIReference, 4 | staticBinding: StaticBinding.Type) -> StaticBinding.SwiftObject 5 | } 6 | 7 | public struct DefaultSwiftWrapperFactory: SwiftWrapperFactory { 8 | public init() {} 9 | 10 | public func create( 11 | _ reference: consuming StaticBinding.ABIReference, 12 | staticBinding: StaticBinding.Type) -> StaticBinding.SwiftObject { 13 | StaticBinding._wrap(consume reference) 14 | } 15 | } 16 | 17 | public var swiftWrapperFactory: any SwiftWrapperFactory = DefaultSwiftWrapperFactory() -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/WeakReference.swift: -------------------------------------------------------------------------------- 1 | import COM 2 | import WindowsRuntime_ABI 3 | 4 | /// A weak reference to a WinRT object. 5 | public final class WeakReference { 6 | private var weakReference: COMReference 7 | 8 | public init(_ target: Binding.SwiftObject) throws { 9 | guard let targetInspectable = target as? IInspectable else { throw COMError.invalidArg } 10 | let source = try targetInspectable._queryInterface( 11 | uuidof(SWRT_IWeakReferenceSource.self), type: SWRT_IWeakReferenceSource.self) 12 | self.weakReference = .init(transferringRef: try Self.getWeakReference(source.pointer)) 13 | } 14 | 15 | // Workaround compiler crash when this code is inlined 16 | private static func getWeakReference( 17 | _ source: UnsafeMutablePointer) 18 | throws -> UnsafeMutablePointer { 19 | var weakReference: UnsafeMutablePointer? 20 | try WinRTError.fromABI(source.pointee.VirtualTable.pointee.GetWeakReference(source, &weakReference)) 21 | if let weakReference { return weakReference } 22 | throw COMError.fail 23 | } 24 | 25 | public func resolve() throws -> Binding.SwiftObject? { 26 | var inspectableTarget: UnsafeMutablePointer? = nil 27 | var iid = GUIDBinding.toABI(Binding.interfaceID) 28 | try WinRTError.fromABI(weakReference.pointer.pointee.VirtualTable.pointee.Resolve( 29 | weakReference.pointer, &iid, &inspectableTarget)) 30 | var target = Binding.ABIPointer(OpaquePointer(inspectableTarget)) 31 | return Binding.fromABI(consuming: &target) 32 | } 33 | } -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/WinRTError+LanguageException.swift: -------------------------------------------------------------------------------- 1 | extension WinRTError { 2 | /// Wraps a Swift Error object so it can be associated with an `IRestrictedErrorInfo`. 3 | internal final class LanguageException: COMExportBase { 4 | public let error: Error 5 | 6 | public init(error: Error) { 7 | self.error = error 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/WinRTImport.swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime_ABI 2 | import COM 3 | import WinSDK 4 | 5 | open class WinRTImport: COMImport, IInspectableProtocol { 6 | private var _inspectableInterop: COMInterop { 7 | .init(casting: _interop) 8 | } 9 | 10 | public func getIids() throws -> [COMInterfaceID] { 11 | try _inspectableInterop.getIids() 12 | } 13 | 14 | public func getRuntimeClassName() throws -> String { 15 | try _inspectableInterop.getRuntimeClassName() 16 | } 17 | 18 | public func getTrustLevel() throws -> TrustLevel { 19 | try _inspectableInterop.getTrustLevel() 20 | } 21 | } -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/WinRTInitialization.swift: -------------------------------------------------------------------------------- 1 | import WindowsRuntime_ABI 2 | 3 | // Initializes WinRT for the current thread. 4 | public final class WinRTInitialization { 5 | public init(multithreaded: Bool) throws { 6 | WindowsRuntime_ABI.SWRT_RoInitialize(multithreaded 7 | ? WindowsRuntime_ABI.SWRT_RO_INIT_MULTITHREADED 8 | : WindowsRuntime_ABI.SWRT_RO_INIT_SINGLETHREADED) 9 | } 10 | 11 | deinit { 12 | WindowsRuntime_ABI.SWRT_RoUninitialize() 13 | } 14 | } -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/WinRTTearOffBase.swift: -------------------------------------------------------------------------------- 1 | import COM 2 | 3 | /// Base class for COM tear-off objects for interfaces derived from IInspectable. 4 | open class WinRTTearOffBase: COMTearOffBase, IInspectableProtocol { 5 | public init(owner: IInspectable) { 6 | super.init(owner: owner) 7 | } 8 | 9 | // Delegate to the identity object, though we should be using that object's IInspectable implementation in the first place. 10 | public func getIids() throws -> [COMInterfaceID] { try (owner as! IInspectable).getIids() } 11 | public func getRuntimeClassName() throws -> String { try (owner as! IInspectable).getRuntimeClassName() } 12 | public func getTrustLevel() throws -> TrustLevel { try (owner as! IInspectable).getTrustLevel() } 13 | } 14 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime/winrtIdentical.swift: -------------------------------------------------------------------------------- 1 | import COM 2 | 3 | /// Determines whether two WinRT references are implemented by the same underlying object. 4 | public func winrtIdentical(_ lhs: IInspectable, _ rhs: IInspectable) -> Bool { 5 | comIdentical(lhs, rhs) 6 | } -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB SOURCES *.c) 2 | add_library(WindowsRuntime_ABI STATIC ${SOURCES}) 3 | target_include_directories(WindowsRuntime_ABI PUBLIC include) 4 | target_link_libraries(WindowsRuntime_ABI PUBLIC COM_ABI) -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/include/SWRT/modules/WindowsRuntime.h: -------------------------------------------------------------------------------- 1 | #include "SWRT/modules/COM.h" 2 | 3 | #include "SWRT/winapi/activation.h" 4 | #include "SWRT/winapi/eventtoken.h" 5 | #include "SWRT/winapi/inspectable.h" 6 | #include "SWRT/winapi/memorybuffer.h" 7 | #include "SWRT/winapi/restrictederrorinfo.h" 8 | #include "SWRT/winapi/roapi.h" 9 | #include "SWRT/winapi/robuffer.h" 10 | #include "SWRT/winapi/roerrorapi.h" 11 | #include "SWRT/winapi/weakreference.h" 12 | #include "SWRT/winapi/winstring.h" 13 | #include "SWRT/winapi/windows.foundation.ireference.h" -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/include/SWRT/winapi/activation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/inspectable.h" 4 | 5 | // IActivationFactory 6 | typedef struct SWRT_IActivationFactory { 7 | struct SWRT_IActivationFactory_VirtualTable* VirtualTable; 8 | } SWRT_IActivationFactory; 9 | 10 | struct SWRT_IActivationFactory_VirtualTable { 11 | SWRT_HResult (__stdcall *QueryInterface)(SWRT_IActivationFactory* _this, SWRT_Guid* riid, void** ppvObject); 12 | uint32_t (__stdcall *AddRef)(SWRT_IActivationFactory* _this); 13 | uint32_t (__stdcall *Release)(SWRT_IActivationFactory* _this); 14 | SWRT_HResult (__stdcall *GetIids)(SWRT_IActivationFactory* _this, uint32_t* iidCount, SWRT_Guid** iids); 15 | SWRT_HResult (__stdcall *GetRuntimeClassName)(SWRT_IActivationFactory* _this, SWRT_HString* className); 16 | SWRT_HResult (__stdcall *GetTrustLevel)(SWRT_IActivationFactory* _this, SWRT_TrustLevel* trustLevel); 17 | SWRT_HResult (__stdcall *ActivateInstance)(SWRT_IActivationFactory* _this, SWRT_IInspectable** instance); 18 | }; 19 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/include/SWRT/winapi/eventtoken.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // EventRegistrationToken 6 | typedef struct SWRT_EventRegistrationToken { 7 | int64_t value; 8 | } SWRT_EventRegistrationToken; 9 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/include/SWRT/winapi/inspectable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/unknwn.h" 4 | #include "SWRT/winapi/winstring.h" 5 | 6 | // TrustLevel 7 | typedef int32_t SWRT_TrustLevel; 8 | 9 | // IInspectable 10 | typedef struct SWRT_IInspectable { 11 | struct SWRT_IInspectable_VirtualTable* VirtualTable; 12 | } SWRT_IInspectable; 13 | 14 | struct SWRT_IInspectable_VirtualTable { 15 | SWRT_HResult (__stdcall *QueryInterface)(SWRT_IInspectable* _this, SWRT_Guid* riid, void** ppvObject); 16 | uint32_t (__stdcall *AddRef)(SWRT_IInspectable* _this); 17 | uint32_t (__stdcall *Release)(SWRT_IInspectable* _this); 18 | SWRT_HResult (__stdcall *GetIids)(SWRT_IInspectable* _this, uint32_t* iidCount, SWRT_Guid** iids); 19 | SWRT_HResult (__stdcall *GetRuntimeClassName)(SWRT_IInspectable* _this, SWRT_HString* className); 20 | SWRT_HResult (__stdcall *GetTrustLevel)(SWRT_IInspectable* _this, SWRT_TrustLevel* trustLevel); 21 | }; 22 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/include/SWRT/winapi/memorybuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/unknwn.h" 4 | 5 | typedef struct SWRT_IMemoryBufferByteAccess SWRT_IMemoryBufferByteAccess; 6 | 7 | struct SWRT_IMemoryBufferByteAccess_VirtualTable { 8 | SWRT_HResult (__stdcall* QueryInterface)(SWRT_IMemoryBufferByteAccess* _this, SWRT_Guid* riid, void** ppvObject); 9 | uint32_t (__stdcall* AddRef)(SWRT_IMemoryBufferByteAccess* _this); 10 | uint32_t (__stdcall* Release)(SWRT_IMemoryBufferByteAccess* _this); 11 | SWRT_HResult (__stdcall* GetBuffer)(SWRT_IMemoryBufferByteAccess* _this, uint8_t** value, uint32_t* capacity); 12 | }; 13 | 14 | struct SWRT_IMemoryBufferByteAccess { 15 | struct SWRT_IMemoryBufferByteAccess_VirtualTable* VirtualTable; 16 | }; 17 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/include/SWRT/winapi/roapi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/activation.h" 4 | #include "SWRT/winapi/BaseTsd.h" 5 | #include "SWRT/winapi/winstring.h" 6 | 7 | typedef enum SWRT_RO_INIT_TYPE { 8 | SWRT_RO_INIT_SINGLETHREADED = 0, 9 | SWRT_RO_INIT_MULTITHREADED = 1 10 | } SWRT_RO_INIT_TYPE; 11 | 12 | typedef SWRT_HResult(__stdcall *SWRT_DllGetActivationFactory)(SWRT_HString activatableClassId, SWRT_IActivationFactory** factory); 13 | SWRT_HResult SWRT_RoGetActivationFactory(SWRT_HString activatableClassId, SWRT_Guid* iid, void** factory); 14 | SWRT_HResult SWRT_RoInitialize(SWRT_RO_INIT_TYPE initType); 15 | void SWRT_RoUninitialize(); 16 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/include/SWRT/winapi/robuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/unknwn.h" 4 | 5 | typedef struct SWRT_IBufferByteAccess SWRT_IBufferByteAccess; 6 | 7 | struct SWRT_IBufferByteAccess_VirtualTable { 8 | SWRT_HResult (__stdcall* QueryInterface)(SWRT_IBufferByteAccess* _this, SWRT_Guid* riid, void** ppvObject); 9 | uint32_t (__stdcall* AddRef)(SWRT_IBufferByteAccess* _this); 10 | uint32_t (__stdcall* Release)(SWRT_IBufferByteAccess* _this); 11 | SWRT_HResult (__stdcall* Buffer)(SWRT_IBufferByteAccess* _this, uint8_t** data); 12 | }; 13 | 14 | struct SWRT_IBufferByteAccess { 15 | struct SWRT_IBufferByteAccess_VirtualTable* VirtualTable; 16 | }; 17 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/include/SWRT/winapi/roerrorapi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "SWRT/winapi/unknwn.h" 5 | #include "SWRT/winapi/restrictederrorinfo.h" 6 | #include "SWRT/winapi/winstring.h" 7 | 8 | typedef enum { 9 | SWRT_RO_ERROR_REPORTING_NONE = 0x00000000, 10 | SWRT_RO_ERROR_REPORTING_SUPPRESSEXCEPTIONS = 0x00000001, 11 | SWRT_RO_ERROR_REPORTING_FORCEEXCEPTIONS = 0x00000002, 12 | SWRT_RO_ERROR_REPORTING_USESETERRORINFO = 0x00000004, 13 | SWRT_RO_ERROR_REPORTING_SUPPRESSSETERRORINFO = 0x00000008, 14 | } SWRT_RO_ERROR_REPORTING_FLAGS; 15 | 16 | SWRT_HResult SWRT_GetRestrictedErrorInfo(SWRT_IRestrictedErrorInfo** ppRestrictedErrorInfo); 17 | SWRT_HResult SWRT_RoCaptureErrorContext(SWRT_HResult hr); 18 | void SWRT_RoClearError(); 19 | void SWRT_RoFailFastWithErrorContext(SWRT_HResult hrError); 20 | SWRT_HResult SWRT_RoGetErrorReportingFlags(uint32_t* pflags); 21 | SWRT_HResult SWRT_RoGetMatchingRestrictedErrorInfo(SWRT_HResult hrIn, SWRT_IRestrictedErrorInfo** ppRestrictedErrorInfo); 22 | bool SWRT_RoOriginateError(SWRT_HResult error, SWRT_HString message); 23 | bool SWRT_RoOriginateErrorW(SWRT_HResult error, uint32_t cchMax, const char16_t* message); 24 | bool SWRT_RoOriginateLanguageException(SWRT_HResult error, SWRT_HString message, SWRT_IUnknown* languageException); 25 | SWRT_HResult SWRT_RoReportUnhandledError(SWRT_IRestrictedErrorInfo* pRestrictedErrorInfo); 26 | SWRT_HResult SWRT_RoSetErrorReportingFlags(uint32_t flags); 27 | SWRT_HResult SWRT_RoTransformError(SWRT_HResult oldError, SWRT_HResult newError, SWRT_HString message); 28 | SWRT_HResult SWRT_SetRestrictedErrorInfo(SWRT_IRestrictedErrorInfo* pRestrictedErrorInfo); -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/include/SWRT/winapi/weakreference.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/inspectable.h" 4 | 5 | typedef struct SWRT_IWeakReference { 6 | struct SWRT_IWeakReference_VirtualTable* VirtualTable; 7 | } SWRT_IWeakReference; 8 | 9 | struct SWRT_IWeakReference_VirtualTable { 10 | SWRT_HResult (__stdcall *QueryInterface)(SWRT_IWeakReference* _this, SWRT_Guid* riid, void** ppvObject); 11 | uint32_t (__stdcall *AddRef)(SWRT_IWeakReference* _this); 12 | uint32_t (__stdcall *Release)(SWRT_IWeakReference* _this); 13 | SWRT_HResult (__stdcall *Resolve)(SWRT_IWeakReference* _this, SWRT_Guid* riid, SWRT_IInspectable** objectReference); 14 | }; 15 | 16 | typedef struct SWRT_IWeakReferenceSource { 17 | struct SWRT_IWeakReferenceSource_VirtualTable* VirtualTable; 18 | } SWRT_IWeakReferenceSource; 19 | 20 | struct SWRT_IWeakReferenceSource_VirtualTable { 21 | SWRT_HResult (__stdcall *QueryInterface)(SWRT_IWeakReferenceSource* _this, SWRT_Guid* riid, void** ppvObject); 22 | uint32_t (__stdcall *AddRef)(SWRT_IWeakReferenceSource* _this); 23 | uint32_t (__stdcall *Release)(SWRT_IWeakReferenceSource* _this); 24 | SWRT_HResult (__stdcall *GetWeakReference)(SWRT_IWeakReferenceSource* _this, SWRT_IWeakReference** weakReference); 25 | }; 26 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/include/SWRT/winapi/winstring.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "SWRT/winapi/BaseTsd.h" 6 | 7 | typedef struct SWRT_HString_* SWRT_HString; 8 | typedef struct SWRT_HStringBuffer_* SWRT_HStringBuffer; 9 | 10 | SWRT_HResult SWRT_WindowsCreateString(const char16_t* sourceString, uint32_t length, SWRT_HString* string); 11 | SWRT_HResult SWRT_WindowsDeleteString(SWRT_HString string); 12 | SWRT_HResult SWRT_WindowsDeleteStringBuffer(SWRT_HStringBuffer bufferHandle); 13 | SWRT_HResult SWRT_WindowsDuplicateString(SWRT_HString string, SWRT_HString* newString); 14 | const char16_t* SWRT_WindowsGetStringRawBuffer(SWRT_HString string, uint32_t* length); 15 | SWRT_HResult SWRT_WindowsPreallocateStringBuffer(uint32_t length, char16_t** charBuffer, SWRT_HStringBuffer* bufferHandle); 16 | SWRT_HResult SWRT_WindowsPromoteStringBuffer(SWRT_HStringBuffer bufferHandle, SWRT_HString* string); -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/include/module.modulemap: -------------------------------------------------------------------------------- 1 | module WindowsRuntime_ABI { 2 | header "SWRT/modules/WindowsRuntime.h" 3 | header "SWRT/winapi/activation.h" 4 | header "SWRT/winapi/eventtoken.h" 5 | header "SWRT/winapi/inspectable.h" 6 | header "SWRT/winapi/memorybuffer.h" 7 | header "SWRT/winapi/restrictederrorinfo.h" 8 | header "SWRT/winapi/roapi.h" 9 | header "SWRT/winapi/robuffer.h" 10 | header "SWRT/winapi/roerrorapi.h" 11 | header "SWRT/winapi/weakreference.h" 12 | header "SWRT/winapi/winstring.h" 13 | export * 14 | } 15 | 16 | module SWRT_WindowsFoundation { 17 | header "SWRT/winapi/windows.foundation.h" 18 | export * 19 | } 20 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/roapi.c: -------------------------------------------------------------------------------- 1 | #include "SWRT/winapi/roapi.h" 2 | 3 | #include 4 | #include 5 | 6 | SWRT_HResult SWRT_RoGetActivationFactory(SWRT_HString activatableClassId, SWRT_Guid* iid, void** factory) { 7 | return (SWRT_HResult)RoGetActivationFactory((HSTRING)activatableClassId, (IID*)iid, factory); 8 | } 9 | 10 | SWRT_HResult SWRT_RoInitialize(SWRT_RO_INIT_TYPE initType) { 11 | return (SWRT_HResult)RoInitialize((RO_INIT_TYPE)initType); 12 | } 13 | 14 | void SWRT_RoUninitialize() { 15 | RoUninitialize(); 16 | } 17 | -------------------------------------------------------------------------------- /Support/Sources/WindowsRuntime_ABI/winstring.c: -------------------------------------------------------------------------------- 1 | #include "SWRT/winapi/winstring.h" 2 | 3 | #include 4 | 5 | SWRT_HResult SWRT_WindowsCreateString(const char16_t* sourceString, uint32_t length, SWRT_HString* string) { 6 | return (SWRT_HResult)WindowsCreateString((PCNZWCH)sourceString, (UINT32)length, (HSTRING*)string); 7 | } 8 | 9 | SWRT_HResult SWRT_WindowsDeleteString(SWRT_HString string) { 10 | return (SWRT_HResult)WindowsDeleteString((HSTRING)string); 11 | } 12 | 13 | SWRT_HResult SWRT_WindowsDeleteStringBuffer(SWRT_HStringBuffer bufferHandle) { 14 | return (SWRT_HResult)WindowsDeleteStringBuffer((HSTRING_BUFFER)bufferHandle); 15 | } 16 | 17 | SWRT_HResult SWRT_WindowsDuplicateString(SWRT_HString string, SWRT_HString *newString) { 18 | return (SWRT_HResult)WindowsDuplicateString((HSTRING)string, (HSTRING*)newString); 19 | } 20 | 21 | const char16_t* SWRT_WindowsGetStringRawBuffer(SWRT_HString string, uint32_t *length) { 22 | return (const char16_t*)WindowsGetStringRawBuffer((HSTRING)string, (UINT32*)length); 23 | } 24 | 25 | SWRT_HResult SWRT_WindowsPreallocateStringBuffer(uint32_t length, char16_t** charBuffer, SWRT_HStringBuffer* bufferHandle) { 26 | return (SWRT_HResult)WindowsPreallocateStringBuffer((UINT32)length, (PWSTR*)charBuffer, (HSTRING_BUFFER*)bufferHandle); 27 | } 28 | 29 | SWRT_HResult SWRT_WindowsPromoteStringBuffer(SWRT_HStringBuffer bufferHandle, SWRT_HString* string) { 30 | return (SWRT_HResult)WindowsPromoteStringBuffer((HSTRING_BUFFER)bufferHandle, (HSTRING*)string); 31 | } 32 | -------------------------------------------------------------------------------- /Support/Tests/ABI/include/SWRT_ICOMTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/unknwn.h" 4 | 5 | // ICOMTest 6 | typedef struct SWRT_ICOMTest { 7 | struct SWRT_ICOMTest_VirtualTable* VirtualTable; 8 | } SWRT_ICOMTest; 9 | 10 | struct SWRT_ICOMTest_VirtualTable { 11 | SWRT_HResult (__stdcall *QueryInterface)(SWRT_ICOMTest* _this, SWRT_Guid* riid, void** ppvObject); 12 | uint32_t (__stdcall *AddRef)(SWRT_ICOMTest* _this); 13 | uint32_t (__stdcall *Release)(SWRT_ICOMTest* _this); 14 | SWRT_HResult (__stdcall *COMTest)(SWRT_ICOMTest* _this); 15 | }; 16 | -------------------------------------------------------------------------------- /Support/Tests/ABI/include/SWRT_ICOMTest2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/unknwn.h" 4 | 5 | // ICOMTest2 6 | typedef struct SWRT_ICOMTest2 { 7 | struct SWRT_ICOMTest2_VirtualTable* VirtualTable; 8 | } SWRT_ICOMTest2; 9 | 10 | struct SWRT_ICOMTest2_VirtualTable { 11 | SWRT_HResult (__stdcall *QueryInterface)(SWRT_ICOMTest2* _this, SWRT_Guid* riid, void** ppvObject); 12 | uint32_t (__stdcall *AddRef)(SWRT_ICOMTest2* _this); 13 | uint32_t (__stdcall *Release)(SWRT_ICOMTest2* _this); 14 | SWRT_HResult (__stdcall *COMTest2)(SWRT_ICOMTest2* _this); 15 | }; 16 | -------------------------------------------------------------------------------- /Support/Tests/ABI/include/SWRT_IWinRTTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SWRT/winapi/inspectable.h" 4 | 5 | // IWinRTTest 6 | typedef struct SWRT_IWinRTTest { 7 | struct SWRT_IWinRTTest_VirtualTable* VirtualTable; 8 | } SWRT_IWinRTTest; 9 | 10 | struct SWRT_IWinRTTest_VirtualTable { 11 | SWRT_HResult (__stdcall *QueryInterface)(SWRT_IWinRTTest* _this, SWRT_Guid* riid, void** ppvObject); 12 | uint32_t (__stdcall *AddRef)(SWRT_IWinRTTest* _this); 13 | uint32_t (__stdcall *Release)(SWRT_IWinRTTest* _this); 14 | SWRT_HResult (__stdcall *GetIids)(SWRT_IWinRTTest* _this, uint32_t* iidCount, SWRT_Guid** iids); 15 | SWRT_HResult (__stdcall *GetRuntimeClassName)(SWRT_IWinRTTest* _this, SWRT_HString* className); 16 | SWRT_HResult (__stdcall *GetTrustLevel)(SWRT_IWinRTTest* _this, SWRT_TrustLevel* trustLevel); 17 | SWRT_HResult (__stdcall *WinRTTest)(SWRT_IWinRTTest* _this); 18 | }; 19 | -------------------------------------------------------------------------------- /Support/Tests/ABI/include/module.modulemap: -------------------------------------------------------------------------------- 1 | module TestsABI { 2 | header "SWRT_ICOMTest.h" 3 | header "SWRT_ICOMTest2.h" 4 | header "SWRT_IWinRTTest.h" 5 | export * 6 | } 7 | -------------------------------------------------------------------------------- /Support/Tests/Tests/HResultTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import COM 3 | 4 | internal final class HResultTests: XCTestCase { 5 | func testMessageHasNoTrailingWhitespace() throws { 6 | guard let message = HResult.ok.message else { throw XCTSkip("No message was available") } 7 | guard let lastChar = message.last else { throw XCTSkip("Message was empty") } 8 | XCTAssert(!lastChar.isWhitespace) 9 | } 10 | } -------------------------------------------------------------------------------- /Support/Tests/Tests/HStringTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import WindowsRuntime 3 | 4 | internal final class HStringTests: XCTestCase { 5 | func testEmptyString() throws { 6 | XCTAssertNil(try HString.create("").detach()) 7 | XCTAssertEqual(HString.toString(nil), "") 8 | } 9 | 10 | func testRoundTrip() throws { 11 | func assertRoundTrip(_ str: String) throws{ 12 | let roundtripped = try HString.create(str).toString() 13 | XCTAssertEqual(str, roundtripped) 14 | } 15 | 16 | try assertRoundTrip("") 17 | try assertRoundTrip("a") 18 | try assertRoundTrip("à") 19 | try assertRoundTrip("☃") 20 | } 21 | } -------------------------------------------------------------------------------- /Support/Tests/Tests/IReferenceToOptionalTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import WindowsRuntime 3 | 4 | internal final class IReferenceToOptionalTests: WinRTTestCase { 5 | func testCreateNumeric() throws { 6 | XCTAssertNil(try Int32Binding.IReferenceToOptional.toABI(nil)) 7 | XCTAssertNil(Int32Binding.IReferenceToOptional.fromABI(nil)) 8 | 9 | var boxed = try Int32Binding.IReferenceToOptional.toABI(42) 10 | defer { Int32Binding.IReferenceToOptional.release(&boxed) } 11 | XCTAssertEqual(Int32Binding.IReferenceToOptional.fromABI(boxed), 42) 12 | } 13 | } -------------------------------------------------------------------------------- /Support/Tests/Tests/Support/ICOMTest.swift: -------------------------------------------------------------------------------- 1 | import COM 2 | 3 | internal typealias ICOMTest = any ICOMTestProtocol 4 | internal protocol ICOMTestProtocol: IUnknownProtocol { 5 | func comTest() throws 6 | } 7 | 8 | import TestsABI 9 | 10 | internal enum ICOMTestBinding: COMTwoWayBinding { 11 | public typealias SwiftObject = ICOMTest 12 | public typealias ABIStruct = SWRT_ICOMTest 13 | 14 | public static var interfaceID: COMInterfaceID { uuidof(ABIStruct.self) } 15 | public static var exportedVirtualTable: VirtualTablePointer { .init(&virtualTable) } 16 | 17 | public static func _wrap(_ reference: consuming ABIReference) -> SwiftObject { 18 | Import(_wrapping: reference) 19 | } 20 | 21 | public static func toCOM(_ object: SwiftObject) throws -> ABIReference { 22 | try Import.toCOM(object) 23 | } 24 | 25 | private final class Import: COMImport, ICOMTestProtocol { 26 | public func comTest() throws { try _interop.comTest() } 27 | } 28 | 29 | private static var virtualTable: SWRT_ICOMTest_VirtualTable = .init( 30 | QueryInterface: { IUnknownVirtualTable.QueryInterface($0, $1, $2) }, 31 | AddRef: { IUnknownVirtualTable.AddRef($0) }, 32 | Release: { IUnknownVirtualTable.Release($0) }, 33 | COMTest: { this in _implement(this) { try $0.comTest() } }) 34 | } 35 | 36 | public func uuidof(_: SWRT_ICOMTest.Type) -> COMInterfaceID { 37 | .init(0x5CF9DEB3, 0xD7C6, 0x42A9, 0x85B3, 0x61D8B68A7B2A) 38 | } 39 | 40 | extension COMInterop where ABIStruct == SWRT_ICOMTest { 41 | public func comTest() throws { 42 | try COMError.fromABI(this.pointee.VirtualTable.pointee.COMTest(this)) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Support/Tests/Tests/Support/ICOMTest2.swift: -------------------------------------------------------------------------------- 1 | import COM 2 | 3 | internal typealias ICOMTest2 = any ICOMTest2Protocol 4 | internal protocol ICOMTest2Protocol: IUnknownProtocol { 5 | func comTest2() throws 6 | } 7 | 8 | import TestsABI 9 | 10 | internal enum ICOMTest2Binding: COMTwoWayBinding { 11 | public typealias SwiftObject = ICOMTest2 12 | public typealias ABIStruct = TestsABI.SWRT_ICOMTest2 13 | 14 | public static var interfaceID: COMInterfaceID { uuidof(ABIStruct.self) } 15 | public static var exportedVirtualTable: VirtualTablePointer { .init(&virtualTable) } 16 | 17 | public static func _wrap(_ reference: consuming ABIReference) -> SwiftObject { 18 | Import(_wrapping: reference) 19 | } 20 | 21 | public static func toCOM(_ object: SwiftObject) throws -> ABIReference { 22 | try Import.toCOM(object) 23 | } 24 | 25 | private final class Import: COMImport, ICOMTest2Protocol { 26 | public func comTest2() throws { try _interop.comTest2() } 27 | } 28 | 29 | private static var virtualTable: SWRT_ICOMTest2_VirtualTable = .init( 30 | QueryInterface: { IUnknownVirtualTable.QueryInterface($0, $1, $2) }, 31 | AddRef: { IUnknownVirtualTable.AddRef($0) }, 32 | Release: { IUnknownVirtualTable.Release($0) }, 33 | COMTest2: { this in _implement(this) { try $0.comTest2() } }) 34 | } 35 | 36 | public func uuidof(_: SWRT_ICOMTest2.Type) -> COMInterfaceID { 37 | .init(0x5CF9DEB3, 0xD7C6, 0x42A9, 0x85B3, 0x61D8B68A7B2B) 38 | } 39 | 40 | extension COMInterop where ABIStruct == SWRT_ICOMTest2 { 41 | public func comTest2() throws { 42 | try COMError.fromABI(this.pointee.VirtualTable.pointee.COMTest2(this)) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Support/Tests/Tests/Support/WinRTTestCase.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import WindowsRuntime 3 | 4 | internal class WinRTTestCase: XCTestCase { 5 | // Due to caching in the projections, we can't deinitialize the WinRT runtime after each test 6 | private static var winRTInitialization: WinRTInitialization? = nil 7 | 8 | override func setUpWithError() throws { 9 | if Self.winRTInitialization == nil { 10 | Self.winRTInitialization = try WinRTInitialization(multithreaded: false) 11 | } 12 | 13 | try super.setUpWithError() 14 | } 15 | } --------------------------------------------------------------------------------