简体   繁体   English

Swift vs Objective C指针操作问题

[英]Swift vs Objective C pointer manipulation issue

I have this code in Objective C which works fine: 我在Objective C中有这个代码可以正常工作:

list = controller->audioBufferList;
list->mBuffers[0].mDataByteSize = inNumberFrames*kSampleWordSize;
list->mBuffers[1].mDataByteSize = inNumberFrames*kSampleWordSize;

And it works fantastic, it updates mDataByteSize field of mBuffers[0] & mBuffers[1]. 它工作得很棒,它更新了mBuffers [0]和mBuffers [1]的mDataByteSize字段。 I tried translating the same in Swift but it doesn't work: 我尝试在Swift中翻译它但它不起作用:

public var audioBufferList:UnsafeMutableAudioBufferListPointer

In function, 在功能上,

let listPtr = controller.audioBufferList.unsafeMutablePointer

let buffers = UnsafeBufferPointer<AudioBuffer>(start: &listPtr.pointee.mBuffers, count: Int(listPtr.pointee.mNumberBuffers))

for var buf in buffers {
    buf.mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
    NSLog("Data byte size \(buf.mDataByteSize)")
}

for buf in buffers {
    NSLog("Data byte size \(buf.mDataByteSize)")
}

The mDataByteSize is not updated. mDataByteSize未更新。 The NSLog on reading back in second for loop points to original values, not updated ones. NSLog在第二次读回环时指向原始值,而不是更新的值。 It seems var buf is referring to another buf by making a copy. 似乎var buf通过制作副本来指代另一个buf。 How do I fix it? 我如何解决它? It's a pure Swift language issue that I am not able to understand. 这是一个纯粹的Swift语言问题,我无法理解。

EDIT: As pointed out by Martin, I fixed the issue by modifying the for loop as 编辑:正如马丁所指出的那样,我通过修改for循环修复了这个问题

 for i in 0..<Int(listPtr.pointee.mNumberBuffers) {
    buffers[i].mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
}

Now it works. 现在它有效。 But that has further aroused my curiosity in Swift Language, how non intuitive it is and how irritating it is for developers who use pointers to manipulate stuff. 但这进一步激起了我对Swift语言的好奇心,它是多么直观,对使用指针操纵东西的开发人员来说是多么恼人。 Why do the following loops fail? 为什么以下循环失败? Are the var buffers copy by value? var缓冲区是否按值复制?

     for buf in buffers {
         var buffer = buf
         buffer.mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
     }

Or 要么

    for var buf in buffers {
        buf.mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
    }

EDIT 2: Hamish's answer raises doubts about validity of using listPtr anywhere. 编辑2:Hamish的回答引起了对在任何地方使用listPtr的有效性的怀疑。 I was using listPtr in a number of calls, such as: 我在一些调用中使用listPtr,例如:

let status = AudioUnitRender(controller.audioUnit!, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, listPtr)

I now need to know where can we use listPtr and where we can not! 我现在需要知道我们在哪里可以使用listPtr以及我们不能使用的地方!

For the call: 致电:

let buffers = UnsafeBufferPointer<AudioBuffer>(start: &listPtr.pointee.mBuffers, count: Int(listPtr.pointee.mNumberBuffers))

&listPtr.pointee.mBuffers produces a temporary pointer valid only for the duration of the call to UnsafeBufferPointer 's initialiser. &listPtr.pointee.mBuffers生成一个临时指针,仅在调用UnsafeBufferPointer的初始化程序时有效。 Therefore attempting to use the buffer pointer results in undefined behaviour (the compiler will hopefully warn on such cases in Swift 5.1). 因此,尝试使用缓冲区指针会导致未定义的行为 (编译器有望在Swift 5.1中对此类情况发出警告 )。

Instead, you can iterate directly over UnsafeMutableAudioBufferListPointer , as it conforms to MutableCollection . 相反,您可以直接在UnsafeMutableAudioBufferListPointer进行迭代,因为它符合MutableCollection

For example: 例如:

for index in audioBufferList.indices {
  audioBufferList[index].mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
  print("Data byte size \(audioBufferList[index].mDataByteSize)")
}

for buffer in audioBufferList {
  print("Data byte size \(buffer.mDataByteSize)")
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM