Swift可变指针被覆盖

时间:2019-03-04 20:35:18

标签: c swift unsafemutablepointer

所以我有一些代码可以对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调用时,可以看到打印出来的leftFacerightFace数组确实是不同的,看起来像这样:

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语言中的打印语句显示左右面的数据不同。只有当我直接在参数中传递函数调用时,它的数据才错误。

那么这是怎么回事?为什么第一种方法无法获得与后者相同的结果?

1 个答案:

答案 0 :(得分:2)

正如一些评论所指出的,这是未定义的行为:

extension Array where Element == Int16 {
    var mutablePointer: UnsafeMutablePointer<Int16> {
        get {
            return UnsafeMutablePointer<Int16>(mutating: self)
        }
    }
}

UnsafeMutablePointer.init(mutating:)返回时,它提供的指针毫无意义。您的意思是符合以下几点:

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是没有意义的,除非您有某种方法来确保所获取的特定对象的寿命,除非在{{ 1}}块。