UnsafeMutablePointer‹Int8› из строки в Swift

Я использую алгоритм dgeev из реализации LAPACK в среде Accelerate для вычисления собственных векторов и собственных значений матрицы. К сожалению, функции LAPACK не описаны в документации Apple с простой ссылкой на http://netlib.org/lapack/faq.html включен.

Если вы посмотрите, то обнаружите, что первые два аргумента в dgeev являются символами, указывающими, следует ли вычислять собственные векторы или нет. В Swift он запрашивает UnsafeMutablePointer<Int8>. Когда я просто использую "N", я получаю сообщение об ошибке. Функция dgeev и ошибка описаны на следующем снимке экранавведите здесь описание изображения

Что мне делать, чтобы решить эту проблему?


person Youssef Moawad    schedule 10.01.2015    source источник


Ответы (3)


«Проблема» заключается в том, что первые два параметра объявлены как char *, а не как const char *, даже если строки не изменяются функцией:

int dgeev_(char *__jobvl, char *__jobvr, ...);

отображается на Swift как

func dgeev_(__jobvl: UnsafeMutablePointer<Int8>, __jobvr: UnsafeMutablePointer<Int8>, ...) -> Int32;

Возможный обходной путь

let result = "N".withCString { 
    dgeev_(UnsafeMutablePointer($0), UnsafeMutablePointer($0), &N, ...)
}

Внутри блока $0 является указателем на завершающийся NUL массив char с представлением строки UTF-8.


Примечание. dgeev_() не изменяет строки, на которые указывают первые два аргумента, поэтому его "должно" объявлять как

int dgeev_(const char *__jobvl, const char *__jobvr, ...);

который будет отображаться на Swift как

func dgeev_(__jobvl: UnsafePointer<Int8>, __jobvr: UnsafePointer<Int8>, ...) -> Int32;

и в этом случае вы могли бы просто назвать это как

let result = dgeev_("N", "N", &N, ...)

поскольку строки Swift автоматически преобразуются в UnsafePointer<Int8>), как описано в значение строки в UnsafePointer‹UInt8 › поведение параметра функции.

person Martin R    schedule 10.01.2015

Это некрасиво, но вы можете использовать:

let unsafePointerOfN = ("N" as NSString).UTF8String
var unsafeMutablePointerOfN: UnsafeMutablePointer<Int8> = UnsafeMutablePointer(unsafePointerOfN)

и используйте unsafeMutablePointerOfN в качестве параметра вместо "N".

person Dániel Nagy    schedule 10.01.2015
comment
У этого решения есть, по крайней мере, теоретическая проблема: строка, возвращаемая .UTF8String, гарантированно действительна только до тех пор, пока существует объект NSString, и она может быть немедленно уничтожена, поскольку после первой строки на нее нет ссылки. Скорее всего, здесь этого не произойдет, потому что строка здесь является буквальной константой. - person Martin R; 10.01.2015

С Swift 4.2 и 5 вы можете использовать аналогичный подход.

let str = "string"
let unsafePointer = UnsafeMutablePointer<Int8>(mutating: (str as NSString).utf8String)

Вы можете получить результат от unsafePointer.

person abdullahselek    schedule 29.05.2019