Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何正确调用CFBinaryHeapGetValues()并在Swift中解析生成的C数组?_Arrays_Swift_Core Foundation_Binary Heap - Fatal编程技术网

Arrays 如何正确调用CFBinaryHeapGetValues()并在Swift中解析生成的C数组?

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

有谁能解释一下如何在Swift中调用Core Foundation的CFBinaryHeap数据结构上的CfBinaryHeapValues吗?一个代码示例/示例将对我有很大帮助。这是我目前拥有的代码:

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)