Swift 可变指针被覆盖
Swift Mutable Pointer being overridden
所以我有一些代码可以对 2 张图像进行深度检测。深度检测发生在本机 C 代码中。为了调用 C 库,我有另一个函数来构建我作为参数传入的 Int16 数组。
然而,当我直接在 C 调用的参数中进行函数调用时,它会覆盖第一个函数调用并两次传入相同的参数。
我的意思是这样的,这是我对C库的调用:
let result = ImageProcessing.depthDetection(leftPhoto.cgImage!,
right: rightPhoto.cgImage!,
leftFace: getFaceDetails(image: leftPhoto, face: leftFace!).mutablePointer,
rightFace: getFaceDetails(image: rightPhoto, face: rightFace!).mutablePointer))
获取面部详细信息调用如下所示:
private func getFaceDetails(image: UIImage, face: VisionFace) -> [Int16] {
var details = [Int16](repeating: 0, count: 10)
// get image size
details[0] = Int16(image.size.width)
details[1] = Int16(image.size.height)
// get face bounds
details[2] = Int16(face.frame.origin.x)
details[3] = Int16(face.frame.origin.y)
details[4] = Int16(face.frame.origin.x + face.frame.width)
details[5] = Int16(face.frame.origin.y + face.frame.height)
// get eye locations
details[6] = Int16(truncating: face.landmark(ofType: .leftEye)?.position.x ?? 0)
details[7] = Int16(truncating: face.landmark(ofType: .leftEye)?.position.y ?? 0)
details[8] = Int16(truncating: face.landmark(ofType: .rightEye)?.position.x ?? 0)
details[9] = Int16(truncating: face.landmark(ofType: .rightEye)?.position.y ?? 0)
print("Details: \(details)")
return details
}
我得到了这个扩展的可变指针:
extension Array where Element == Int16 {
var mutablePointer: UnsafeMutablePointer<Int16> {
get {
return UnsafeMutablePointer<Int16>(mutating: self)
}
}
}
所以当我 运行 上面的 ImageProcessing.depthDetection
调用时,我可以看到打印出我的 leftFace
和 rightFace
数组确实不同并且看起来像这样:
Details: [3088, 2320, 1119, 431, 2230, 1542, 1493, 888, 1892, 882]
Details: [3088, 2320, 864, 446, 1975, 1556, 1207, 900, 1626, 890]
但是当我用 C 打印它们时,它们都与 rightFace
数组相同并且看起来像这样(我以不同的方式格式化我的 C 日志,但你可以看出左右都有相同的数据):
0: Left (3088, 2320), Right (3088, 2320)
1: Left (864, 446), Right (864, 446)
2: Left (1975, 1556), Right (1975, 1556)
3: Left (1207, 900), Right (1207, 900)
4: Left (1626, 890), Right (1626, 890)
那么为什么第一个 getFaceDetails
输出会被第二个输出覆盖?
最奇怪的部分是,如果我将 getFaceDetails
的结果分配给一个变量,然后像我在这里做的那样将该变量作为参数传入:
let lf = getFaceDetails(image: leftPhoto, face: leftFace!)
let rf = getFaceDetails(image: rightPhoto, face: rightFace!)
let result = ImageProcessing.depthDetection(leftPhoto.cgImage!,
right: rightPhoto.cgImage!,
leftFace: lf.mutablePointer,
rightFace: rf.mutablePointer)
然后突然间它起作用了!我在 C 中的打印语句显示左脸和右脸的不同数据。只有当我直接在参数中传递函数调用时,它才会有错误的数据。
所以这是怎么回事?为什么我做的第一种方法产生的结果与后者的结果不一样?
正如一些评论所指出的,这是未定义的行为:
extension Array where Element == Int16 {
var mutablePointer: UnsafeMutablePointer<Int16> {
get {
return UnsafeMutablePointer<Int16>(mutating: self)
}
}
}
一UnsafeMutablePointer.init(mutating:)
returns,它提供的指针就没有意义了。你的意思是这样的:
let result = lf.withUnsafeMutableBytes { lfBytes in
rf.withUnsafeMutableBytes { rfBytes in
return ImageProcessing.depthDetection(leftPhoto.cgImage!,
right: rightPhoto.cgImage!,
leftFace: lfBytes,
rightFace: rhBytes)
}
}
或者,您可以按照以下方式做一些事情:
let result = ImageProcessing.depthDetection(leftPhoto.cgImage!,
right: rightPhoto.cgImage!,
leftFace: &lf,
rightFace: &rf)
但关键是返回 UnsafeMutablePointer
是没有意义的,除非你有某种方法来确保你所指向的特定事物的生命周期,这几乎永远不会是真的,除非在withUnsafe...
块。
所以我有一些代码可以对 2 张图像进行深度检测。深度检测发生在本机 C 代码中。为了调用 C 库,我有另一个函数来构建我作为参数传入的 Int16 数组。
然而,当我直接在 C 调用的参数中进行函数调用时,它会覆盖第一个函数调用并两次传入相同的参数。
我的意思是这样的,这是我对C库的调用:
let result = ImageProcessing.depthDetection(leftPhoto.cgImage!,
right: rightPhoto.cgImage!,
leftFace: getFaceDetails(image: leftPhoto, face: leftFace!).mutablePointer,
rightFace: getFaceDetails(image: rightPhoto, face: rightFace!).mutablePointer))
获取面部详细信息调用如下所示:
private func getFaceDetails(image: UIImage, face: VisionFace) -> [Int16] {
var details = [Int16](repeating: 0, count: 10)
// get image size
details[0] = Int16(image.size.width)
details[1] = Int16(image.size.height)
// get face bounds
details[2] = Int16(face.frame.origin.x)
details[3] = Int16(face.frame.origin.y)
details[4] = Int16(face.frame.origin.x + face.frame.width)
details[5] = Int16(face.frame.origin.y + face.frame.height)
// get eye locations
details[6] = Int16(truncating: face.landmark(ofType: .leftEye)?.position.x ?? 0)
details[7] = Int16(truncating: face.landmark(ofType: .leftEye)?.position.y ?? 0)
details[8] = Int16(truncating: face.landmark(ofType: .rightEye)?.position.x ?? 0)
details[9] = Int16(truncating: face.landmark(ofType: .rightEye)?.position.y ?? 0)
print("Details: \(details)")
return details
}
我得到了这个扩展的可变指针:
extension Array where Element == Int16 {
var mutablePointer: UnsafeMutablePointer<Int16> {
get {
return UnsafeMutablePointer<Int16>(mutating: self)
}
}
}
所以当我 运行 上面的 ImageProcessing.depthDetection
调用时,我可以看到打印出我的 leftFace
和 rightFace
数组确实不同并且看起来像这样:
Details: [3088, 2320, 1119, 431, 2230, 1542, 1493, 888, 1892, 882]
Details: [3088, 2320, 864, 446, 1975, 1556, 1207, 900, 1626, 890]
但是当我用 C 打印它们时,它们都与 rightFace
数组相同并且看起来像这样(我以不同的方式格式化我的 C 日志,但你可以看出左右都有相同的数据):
0: Left (3088, 2320), Right (3088, 2320)
1: Left (864, 446), Right (864, 446)
2: Left (1975, 1556), Right (1975, 1556)
3: Left (1207, 900), Right (1207, 900)
4: Left (1626, 890), Right (1626, 890)
那么为什么第一个 getFaceDetails
输出会被第二个输出覆盖?
最奇怪的部分是,如果我将 getFaceDetails
的结果分配给一个变量,然后像我在这里做的那样将该变量作为参数传入:
let lf = getFaceDetails(image: leftPhoto, face: leftFace!)
let rf = getFaceDetails(image: rightPhoto, face: rightFace!)
let result = ImageProcessing.depthDetection(leftPhoto.cgImage!,
right: rightPhoto.cgImage!,
leftFace: lf.mutablePointer,
rightFace: rf.mutablePointer)
然后突然间它起作用了!我在 C 中的打印语句显示左脸和右脸的不同数据。只有当我直接在参数中传递函数调用时,它才会有错误的数据。
所以这是怎么回事?为什么我做的第一种方法产生的结果与后者的结果不一样?
正如一些评论所指出的,这是未定义的行为:
extension Array where Element == Int16 {
var mutablePointer: UnsafeMutablePointer<Int16> {
get {
return UnsafeMutablePointer<Int16>(mutating: self)
}
}
}
一UnsafeMutablePointer.init(mutating:)
returns,它提供的指针就没有意义了。你的意思是这样的:
let result = lf.withUnsafeMutableBytes { lfBytes in
rf.withUnsafeMutableBytes { rfBytes in
return ImageProcessing.depthDetection(leftPhoto.cgImage!,
right: rightPhoto.cgImage!,
leftFace: lfBytes,
rightFace: rhBytes)
}
}
或者,您可以按照以下方式做一些事情:
let result = ImageProcessing.depthDetection(leftPhoto.cgImage!,
right: rightPhoto.cgImage!,
leftFace: &lf,
rightFace: &rf)
但关键是返回 UnsafeMutablePointer
是没有意义的,除非你有某种方法来确保你所指向的特定事物的生命周期,这几乎永远不会是真的,除非在withUnsafe...
块。