Swift Mutable Pointer переопределяется - PullRequest
0 голосов
/ 04 марта 2019

Итак, у меня есть код для определения глубины на 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))

Вызов Get Face Details выглядит следующим образомэто:

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 показывают разные данные для левого и правого лица.Только когда я передаю вызовы функций непосредственно в параметры, они содержат неверные данные.

Так что здесь происходит?Почему первый способ, которым я делаю это, не дает те же результаты, что и последний?

1 Ответ

0 голосов
/ 05 марта 2019

Как отмечают некоторые из комментариев, это неопределенное поведение:

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 не имеет смысла, если только у вас нет способа обеспечить срок службы конкретной вещи, на которую вы взяли указатель, что почти никогда не соответствует действительности, кроме как в пределах блока withUnsafe....

...