在Swift中从字符串转换为UnsafeMutablePointer<Int8>

6
我正在使用Accelerate框架中的LAPACK实现中的dgeev算法来计算矩阵的特征向量和特征值。遗憾的是,苹果文档中没有对LAPACK函数进行描述,仅提供了一个指向http://netlib.org/lapack/faq.html的链接。
如果您查看它,您会发现dgeev中的前两个参数是表示是否计算特征向量的字符。在Swift中,它要求UnsafeMutablePointer<Int8>。当我简单地使用"N"时,我会收到一个错误。如下截图所示,dgeev函数和错误被描述出来。
我该怎么办才能解决这个问题?
3个回答

4
“问题”在于前两个参数被声明为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>,详细内容请参考String value to UnsafePointer<UInt8> function parameter behavior

3

虽然不美观,但您可以使用以下方法:

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

使用unsafeMutablePointerOfN作为参数,而不是"N"。


这个解决方案至少存在一个理论问题:.UTF8String 返回的字符串只有在 NSString 对象存在的时候才能保证有效,而且由于第一行后没有引用它,所以它可能会立即被销毁。尽管在这里这种情况很少发生,因为这里的字符串是一个字面常量。 - Martin R

0

使用 Swift 4.25,您可以采用类似的方法

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

您可以从unsafePointer获取结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接