2016-12-24 26 views
1

我一直在試圖接口到一個Objective-C庫,它只暴露了指向C結構數組的指針和該數組的計數。與Swift 3中的MemoryRebound不工作的Objective-C結構指針

我已經使用withMemoryRebound結構,並設置容量,因爲我在其他帖子在這裏和其他地方見過。但是,我在Swift中獲得的數組有垃圾數據。作爲解決方法,我在庫中添加了一個訪問器方法。但我真的不想修改這個庫。

下面是一個測試應用程序演示該問題之後的預期結果的組成部分:

Circle.h:

#import <Foundation/Foundation.h> 

typedef struct { 
    float x, y;   /**< Position in pixels. */ 
    float radius;  /**< Radius in pixels. */ 
} circle; 

@interface CircleGenerator : NSObject { 
} 

@property (nonatomic)  size_t    numCircles; 
@property (nonatomic, readonly) const circle* circles; 

- (id)init; 
// Added as a workaround: 
- (void)fetchCircle:(size_t) i circle:(circle *) c; 

@end 

Circle.m:

#import "Circle.h" 

@interface CircleGenerator() 

@end 

const circle myCircles[] = { 
    {.x=2467.38184, .y=338.520477, .radius=140.096466}, 
    {.x=438.689453, .y=1879.302, .radius=116.18354} 
}; 

@implementation CircleGenerator 

- (id)init { 
    _numCircles = 2; 
    _circles = myCircles; 
    return self; 
} 

// Added as a workaround: 
- (void)fetchCircle:(size_t) i circle:(circle *) c { 
    *c = _circles[i]; 
} 

@end 

視圖控制器。 swift:

import UIKit 

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let circleGen = CircleGenerator()! 

     var circlesPtr = UnsafePointer(circleGen.circles) 
     withUnsafePointer(to: &circlesPtr) { 
      $0.withMemoryRebound(to: circle.self, capacity: circleGen.numCircles, { 
       for i in 0..<circleGen.numCircles { 
        print($0[i]) 
       } 
      }) 
     } 
     print("\nShould be:") 
     var nextCircle:circle = circle(x: 0, y: 0, radius: 0) 
     for i in 0..<circleGen.numCircles { 
      circleGen.fetchCircle(i, circle: &nextCircle) 
      print(nextCircle) 
     } 
    }  
} 

輸出:

circle(x: 6.70394638e-38, y: 1.40129846e-45, radius: 2.47778904e+18) 
circle(x: 4.59163468e-41, y: 6.7002974e-38, radius: 1.40129846e-45) 

應該是:

circle(x: 2467.38184, y: 338.520477, radius: 140.096466) 
circle(x: 438.689453, y: 1879.302, radius: 116.18354) 

此外,$0.pointee$.pointee.x等示出了第一元件的不正確的值。

我有缺陷嗎,還是應該向蘋果公司報告?

回答

2

circleGen.circles已經是類型化的指針(UnsafePointer<circle>),就沒有必要使用withUnsafePointer()

for i in 0..<circleGen.numCircles { 
    let circle = circleGen.circles[i] 
    print(circle) 
} 

輸出:

circle(x: 2467.38184, y: 338.520477, radius: 140.096466) 
circle(x: 438.689453, y: 1879.302, radius: 116.18354) 

或創建一個UnsafeBufferPointer這是一個 「陣列狀」收藏:

let circles = UnsafeBufferPointer(start: circleGen.circles, count: circleGen.numCircles) 
for circle in circles { 
    print(circle) 
} 

但是,如果您好奇爲什麼代碼不起作用: 您正在重新綁定指向circlesPtr變量本身的指針, 而不是存儲在該變量中的指針。 你會得到正確的結果

let circlesPtr = UnsafePointer(circleGen.circles)! 
circlesPtr.withMemoryRebound(to: circle.self, capacity: circleGen.numCircles, { 
    for i in 0..<circleGen.numCircles { 
     print($0[i]) 
    } 
}) 
+0

謝謝你馬丁!現在兩種方式都可以工作,我很高興在這種情況下我不需要重新綁定。 – orologics