Соединение с / с CoreFoundation в Linux

Я пытаюсь скомпилировать некоторый код в Linux, который использует как CoreFoundation, так и Foundation, но Linux не реализует мосты так же, как MacOS и iOS.

Соединение Objective-C и Swift работает:

import Foundation
import CoreFoundation
import Glibc

func wantsNSString(_ string: NSString) {
        print(string)
}

let string = "Hello, world!"
wantsNSString(string._bridgeToObjectiveC())

Но я не могу понять, как соединиться с CoreFoundation. Я не могу просто передать NSString к функции, которая хочет CFString:

import Foundation
import CoreFoundation
import Glibc

func wantsCFString(_ string: CFString) {
        print(string)
}

let string = "Hello, world!"
wantsCFString(string._bridgeToObjectiveC()) //error: cannot convert value of type 'String._ObjectType' (aka 'NSString') to expected argument type 'CFString'

Я не могу просто разыграть это как в macOS:

import Foundation
import CoreFoundation
import Glibc

func wantsCFString(_ string: CFString) {
        print(string)
}

let string = "Hello, world!"
wantsCFString(string._bridgeToObjectiveC() as CFString)
//error: 'String._ObjectType' (aka 'NSString') is not convertible to 'CFString'; did you mean to use 'as!' to force downcast?

С помощью as! как сообщение об ошибке предполагает компиляцию, но приводит к падению во время выполнения (Illegal instruction), а также as? выдает ошибку:

error: conditional downcast to CoreFoundation type 'CFString' will always succeed

Bridging.swift имеет протоколы для преобразования между типами NS и CF, и многие типы имеют инициализаторы и свойства, но все они internal или же private, Я мог бы просто использовать CFStringCreateWithCString, но это должно работать с другими парами классов, такими как InputStream а также CFReadStream,

Я что-то здесь упускаю или действительно нет способа конвертировать между типами Foundation и CoreFoundation в Linux?

1 ответ

Решение

Похоже я могу unsafeBitCastNSString в / из CFString:

import Foundation
import CoreFoundation
import Glibc

func wantsCFString(_ string: CFString) {
        print(string)
}

let string = "Hello, world!"
wantsCFString(unsafeBitCast(string._bridgeToObjectiveC(), to: CFString.self)
//prints "Hello, world!"

Это имеет смысл, поскольку типы CoreFoundation и Foundation были спроектированы таким образом, чтобы иметь одинаковую структуру памяти, поэтому работает бесплатный мост. Я несколько удивлен тем, что это работает с реализацией Swift Foundation.

Другие вопросы по тегам