Swift как язык C REPL
Системные программисты, которые часто переключаются между операционными системами, страдают амнезией POSIX. Это когда вы знаете, какую функцию POSIX использовать, но забываете о некоторых крайних случаях, кодах возврата или граничных условиях. Какие флаги состояния по умолчанию F_GETFL
для файлового дескриптора, открытого с O_NONBLOCK
? Что fcntl(fd, F_SETSIZE)
будет делать с «/ dev / null» в macOS?
Оказывается, если у вас установлен Xcode, swift
CLI можно использовать как забавный REPL на языке C.
Запустите swift
CLI из терминала. Чтобы Swift REPL мог использовать многие стандартные функции POSIX, вам также необходимо import Foundation
.
Теперь мы можем запускать функции C. Вот open(2)
:
При вызове open("/dev/null", ...)
возвращается 3
, которое является ожидаемым возвращаемым значением. Возвращаемое значение (зеленое) имеет префикс типа возвращаемого значения Int32
. Int32
Swift (также называемый CInt
) соответствует типу int
C, который предсказуемо является 32-битным на платформах LP64. В конце концов, можно ожидать, что Int
тип Swift будет 64-битным, поэтому Int
отличается от CInt
.
Давайте воспользуемся Swift let
, чтобы зафиксировать возвращаемое значение:
А теперь займемся кое-чем интересным. Давайте восстановим путь к файлу по его файловому дескриптору. К сожалению, это будет немного увлекательно и тяжело. Вот что нужно вырезать и вставить, следуя инструкциям:
import Foundation let fd = open("/dev/null", O_RDONLY) var buf = [UInt8](repeating: 0, count: .init(PATH_MAX)) buf.withUnsafeMutableBytes { ptr in fcntl(fd, F_GETPATH, ptr.baseAddress!) } String(cString: buf)
После ввода последней строки (String(cString: buf)
) мы возвращаем представление значения String
Swift, содержащего путь к файлу:
Думаю, я просто отговорил вас от использования Swift в качестве C REPL со всей этой withUnsafeMadness
сложностью. Давайте попробуем что-нибудь попроще, не требующее никакого управления буфером. Давайте попробуем изменить размер /dev/null
файла и посмотрим, что не получится:
Как видите, это выглядит намного более управляемым, и мы даже восстановили печатаемое сообщение об ошибке, соответствующее ошибке fcntl
.
В качестве последнего примера давайте посмотрим, как получить размер структуры dirent
с помощью Swift. MemoryLayout
можно использовать как замену sizeof
C.
Ну вот и все. Swift REPL можно использовать для тестирования стандартных функций C, проверки значений констант POSIX (и некоторых #define
s) и размеров структур. Может быть удобно или несколько неприятно вызывать определенные вещи, и иногда вам может потребоваться знать больше Swift, чем вы хотели. Но это работает и делает мой день немного проще как на macOS, так и на Linux.