Arrays 如何正确调用CFBinaryHeapGetValues()并在Swift中解析生成的C数组?
有谁能解释一下如何在Swift中调用Core Foundation的CFBinaryHeap数据结构上的CfBinaryHeapValues吗?一个代码示例/示例将对我有很大帮助。这是我目前拥有的代码:Arrays 如何正确调用CFBinaryHeapGetValues()并在Swift中解析生成的C数组?,arrays,swift,core-foundation,binary-heap,Arrays,Swift,Core Foundation,Binary Heap,有谁能解释一下如何在Swift中调用Core Foundation的CFBinaryHeap数据结构上的CfBinaryHeapValues吗?一个代码示例/示例将对我有很大帮助。这是我目前拥有的代码: public class CountedColor : NSObject { public private(set) var count: Int public private(set) var color: UIColor public init(color: UIC
public class CountedColor : NSObject
{
public private(set) var count: Int
public private(set) var color: UIColor
public init(color: UIColor, colorCount: Int)
{
self.count = colorCount
self.color = color
super.init()
}
}
var callbacks = CFBinaryHeapCallBacks()
callbacks.compare = { (a,b,unused) in
let afoo : CountedColor = (a?.assumingMemoryBound(to: CountedColor.self).pointee)!
let bfoo : CountedColor = (b?.assumingMemoryBound(to: CountedColor.self).pointee)!
if ( afoo.count == bfoo.count ) { return CFComparisonResult.compareEqualTo }
if ( afoo.count > bfoo.count ) { return CFComparisonResult.compareGreaterThan }
return CFComparisonResult.compareLessThan
}
let callbackPointer = UnsafeMutablePointer<CFBinaryHeapCallBacks>.allocate(capacity: 1)
callbackPointer.initialize(to: callbacks)
var bh = CFBinaryHeapCreate(nil, 0, callbackPointer, nil)
var fooPointer : UnsafeMutablePointer<CountedColor>!
fooPointer = UnsafeMutablePointer<CountedColor>.allocate(capacity: 1)
fooPointer.initialize(to: CountedColor(color: UIColor.blue, colorCount: 72))
CFBinaryHeapAddValue(bh, fooPointer)
fooPointer = UnsafeMutablePointer<CountedColor>.allocate(capacity: 1)
fooPointer.initialize(to: CountedColor(color: UIColor.red, colorCount: 99))
CFBinaryHeapAddValue(bh, fooPointer)
var elements = [CountedColor](repeating: CountedColor(color: UIColor.white, colorCount: 0), count: 2)
var elementPtr = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: 1)
elementPtr.initialize(to: elements)
CFBinaryHeapGetValues(bh, elementPtr)
var returnedValues: UnsafePointer<[CountedColor]> = (elementPtr.pointee?.assumingMemoryBound(to: [CountedColor].self))!
print(elementPtr.pointee?.assumingMemoryBound(to: CountedColor.self).pointee.count)
print(elementPtr.pointee?.assumingMemoryBound(to: CountedColor.self).pointee.color)
let values = returnedValues.pointee
公共类CountedColor:NSObject
{
公私(集合)变量计数:Int
公共-私有(集合)变量颜色:UIColor
公共初始化(颜色:UIColor,颜色计数:Int)
{
self.count=colorCount
self.color=颜色
super.init()
}
}
var callbacks=CFBinaryHeapCallBacks()
callbacks.compare={(a,b,未使用)在
让afoo:CountedColor=(a?.assumingMemoryBound(to:CountedColor.self).pointee)!
让bfoo:CountedColor=(b?.assumingMemoryBound(to:CountedColor.self).pointee)!
如果(afoo.count==bfoo.count){返回CFComparisonResult.compareEqualTo}
如果(afoo.count>bfoo.count){返回CFComparisonResult.compareGreaterThan}
返回CFComparisonResult.comparilessthan
}
让callbackPointer=unsafemeutablepointer.allocate(容量:1)
callbackPointer.initialize(到:回调)
var bh=CFBinaryHeapCreate(nil,0,callbackPointer,nil)
var fooPointer:unsafemeutablepointer!
fooPointer=unsafemeutablepointer.allocate(容量:1)
fooPointer.initialize(to:CountedColor(color:UIColor.blue,colorCount:72))
CFBinaryHeapAddValue(bh,fooPointer)
fooPointer=unsafemeutablepointer.allocate(容量:1)
fooPointer.initialize(到:CountedColor(color:UIColor.red,colorCount:99))
CFBinaryHeapAddValue(bh,fooPointer)
变量元素=[CountedColor](重复:CountedColor(颜色:UIColor.white,colorCount:0),计数:2)
var elementPtr=UnsafeMutablePointer.allocate(容量:1)
elementPtr.initialize(到:元素)
CFBinaryHeapGetValues(bh、elementPtr)
var returnedValues:UnsafePointer=(elementPtr.pointee?.assumingmemorybind(to:[CountedColor].self))!
打印(elementPtr.pointee?.assumingMemoryBound(to:CountedColor.self).pointee.count)
打印(elementPtr.pointee?.assumingmemorybind(to:CountedColor.self).pointee.color)
let values=returnedValues.pointee
^^如果你看上面的最后三行,代码在最后一行失败,我得到了一个EXC_BAD_访问权限。我不明白为什么,因为上面两个打印语句实际上是有效的。我能够验证该函数返回的C数组中的第一个对象确实是计数为72的较小颜色。这意味着我传入的数组正在用值更新,然而,当我试图通过访问指针对象来获取数组句柄时,事情就乱了套。起初我认为这是一个内存管理问题,但在阅读了Swift中桥接的工作原理后,我不确定情况是否如此,特别是因为这是一个带注释的CoreFoundation API。在您的代码中:
CFBinaryHeapAddValue(bh, fooPointer)
您正在传递一个非女性化指针
,两次
(图元的数量会影响许多零件。)
因此,在调用CFBinaryHeapGetValues(bh,elementPtr)
时,需要为C-array保留一个区域,该区域可以包含两个不可分配指针
你应该这样写:
var elementPtr = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: 2) //<- You need to allocate a region for two elements
elementPtr.initialize(to: nil, count: 2) //<- The content is overwritten, initial values can be nil
CFBinaryHeapGetValues(bh, elementPtr)
UnsafeBufferPointer
用作集合类型,因此您可以轻松地将其转换为数组
let values = returnedValues.map{$0!.load(as: CountedColor.self)}
请不要忘记取消初始化
和取消分配
已分配的区域
要做到这一点,您需要保留所有分配的指针及其计数。因此,您可能需要将部分代码更改为:
var fooPointer : UnsafeMutablePointer<CountedColor>!
fooPointer = UnsafeMutablePointer<CountedColor>.allocate(capacity: 1)
fooPointer.initialize(to: CountedColor(color: UIColor.blue, colorCount: 72))
CFBinaryHeapAddValue(bh, fooPointer)
var barPointer : UnsafeMutablePointer<CountedColor>!
barPointer = UnsafeMutablePointer<CountedColor>.allocate(capacity: 1)
barPointer.initialize(to: CountedColor(color: UIColor.red, colorCount: 99))
CFBinaryHeapAddValue(bh, barPointer)
您可能希望向CFBinaryHeap添加任意数量的CountedColor
s,在这种情况下,您可以编写如下内容:
let colors = [
CountedColor(color: UIColor.blue, colorCount: 72),
CountedColor(color: UIColor.red, colorCount: 99),
//...
]
var fooPointer : UnsafeMutablePointer<CountedColor>!
fooPointer = UnsafeMutablePointer<CountedColor>.allocate(capacity: colors.count)
fooPointer.initialize(from: colors)
for i in colors.indices {
CFBinaryHeapAddValue(bh, fooPointer+i)
}
无论如何,匹配初始化
和取消初始化
,分配
和取消分配
您可能会在Swift标准库中找到一些有用的类型来改进代码,但一次学习太多东西可能不是一个好习惯…我已经投票并接受了您的答案,非常感谢!我现在明白多了。一个快速跟进问题。在您编写的最后一行代码中,load(as:)函数是如何工作的?就我而言,这只是一个空洞的指针。那么Swift怎么可能知道如何读取这些原始字节并创建CountedColor对象呢。我阅读了文档,但仍然没有帮助。这对我来说是神奇的,诚实地来自Objc、C++和C Word,与C的快速交互似乎对我来说是神奇的:(@ AyBayBay,它是如何加载的(AS:)函数?在C中检索某些内容时,您将把<代码>空隙*/COD>转换成一个合适的类型,例如<代码> *((SoMyType *)避免指针)
.Swift中,aVoidPointer.load(as:SomeType.self)
是它的等价物。或者你可以把它看作是aVoidPointer.assumingmemorybind(to:SomeType.self.pointee)的快捷形式。好的,非常感谢:)最后一个跟进问题,我想回顾一下我需要释放/释放的对象。看看代码,我会想象它是callbackPtr,我添加到BinaryHeap的每个不可配置指针对象,最后是elementPtr和其中的对象。。我在这里的理解正确吗?简单地说初始化
和取消初始化
需要匹配,分配
和取消分配
。对于实际的代码,它可能太长了,不能作为一个注释,我稍后会在我的答案中添加一些示例。好的,非常感谢@OOPer,你对困扰我一整天的事情帮助很大。我想我的主要问题是关于fooPointer,我使用它并将两个对象分配到数据结构中,所以我想我需要将它们存储在数组中,并在某个点释放这两个CountedColor。如果这有道理的话,我认为我的理解很好。
var fooPointer : UnsafeMutablePointer<CountedColor>!
fooPointer = UnsafeMutablePointer<CountedColor>.allocate(capacity: 1)
fooPointer.initialize(to: CountedColor(color: UIColor.blue, colorCount: 72))
CFBinaryHeapAddValue(bh, fooPointer)
var barPointer : UnsafeMutablePointer<CountedColor>!
barPointer = UnsafeMutablePointer<CountedColor>.allocate(capacity: 1)
barPointer.initialize(to: CountedColor(color: UIColor.red, colorCount: 99))
CFBinaryHeapAddValue(bh, barPointer)
elementPtr.deinitialize(count: 2)
elementPtr.deallocate(capacity: 2)
barPointer.deinitialize()
barPointer.deallocate(capacity: 1)
fooPointer.deinitialize()
fooPointer.deallocate(capacity: 1)
let colors = [
CountedColor(color: UIColor.blue, colorCount: 72),
CountedColor(color: UIColor.red, colorCount: 99),
//...
]
var fooPointer : UnsafeMutablePointer<CountedColor>!
fooPointer = UnsafeMutablePointer<CountedColor>.allocate(capacity: colors.count)
fooPointer.initialize(from: colors)
for i in colors.indices {
CFBinaryHeapAddValue(bh, fooPointer+i)
}
elementPtr.deinitialize(count: colors.count)
elementPtr.deallocate(capacity: colors.count)
fooPointer.deinitialize(count: colors.count)
fooPointer.deallocate(capacity: colors.count)