Swift 中的 CMBlockBuffer、UnsafeMutablePointer 等
CMBlockBuffer, UnsafeMutablePointer et al in Swift
我正在尝试转换 Apple 代码示例之一中提供的一些 Objective C 代码:https://developer.apple.com/library/mac/samplecode/avsubtitleswriterOSX/Listings/avsubtitleswriter_SubtitlesTextReader_m.html
目前我得到的结果如下:
func copySampleBuffer() -> CMSampleBuffer? {
var textLength : Int = 0
var sampleSize : Int = 0
if (text != nil) {
textLength = text!.characters.count
sampleSize = text!.lengthOfBytesUsingEncoding(NSUTF16StringEncoding)
}
var sampleData = [UInt8]()
// Append text length
sampleData.append(UInt16(textLength).hiByte())
sampleData.append(UInt16(textLength).loByte())
// Append the text
for char in (text?.utf16)! {
sampleData.append(char.bigEndian.hiByte())
sampleData.append(char.bigEndian.loByte())
}
if (self.forced) {
// TODO
}
let samplePtr = UnsafeMutablePointer<[UInt8]>.alloc(1)
samplePtr.memory = sampleData
var sampleTiming = CMSampleTimingInfo()
sampleTiming.duration = self.timeRange.duration;
sampleTiming.presentationTimeStamp = self.timeRange.start;
sampleTiming.decodeTimeStamp = kCMTimeInvalid;
let formatDescription = copyFormatDescription()
let dataBufferUMP = UnsafeMutablePointer<Optional<CMBlockBuffer>>.alloc(1)
CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, samplePtr, sampleSize, kCFAllocatorMalloc, nil, 0, sampleSize, 0, dataBufferUMP);
let sampleBufferUMP = UnsafeMutablePointer<Optional<CMSampleBuffer>>.alloc(1)
CMSampleBufferCreate(kCFAllocatorDefault, dataBufferUMP.memory, true, nil, nil, formatDescription, 1, 1, &sampleTiming, 1, &sampleSize, sampleBufferUMP);
let sampleBuffer = sampleBufferUMP.memory
sampleBufferUMP.destroy()
sampleBufferUMP.dealloc(1)
dataBufferUMP.destroy()
dataBufferUMP.dealloc(1)
samplePtr.destroy()
//Crash if I call dealloc here
//Error is: error for object 0x10071e400: pointer being freed was not allocated
//samplePtr.dealloc(1)
return sampleBuffer;
}
我想尽可能避免使用 "Unsafe*" 类型,尽管我不确定这里是否可行。我还查看了使用结构,然后以某种方式看到以某种方式打包它,但我看到的示例似乎基于 sizeof,它使用定义的大小,而不是结构的当前大小。这将是我会使用的结构:
struct SubtitleAtom {
var length : UInt16
var text : [UInt16]
var forced : Bool?
}
任何有关最适合此功能的 Swift2 代码的建议将不胜感激。
所以,首先,您的代码使用此模式
class C { deinit { print("I got deinit'd!") } }
struct S { var objectRef:AnyObject? }
func foo() {
let ptr = UnsafeMutablePointer<S>.alloc(1)
let o = C()
let fancy = S(objectRef: o)
ptr.memory = fancy
ptr.destroy() //deinit runs here!
ptr.dealloc(1) //don't leak memory
}
// soon or later this code should crash :-)
(1..<1000).forEach{ i in
foo()
print(i)
}
在操场上试一试,很可能会崩溃 :-)。它出什么问题了?问题是您的 不平衡的保留/释放周期 。如何以安全的方式编写相同的内容?您删除了 dealloc 部分。但尝试在我的代码片段中执行此操作并查看结果。代码再次崩溃:-)。唯一安全的方法是正确初始化和取消初始化(销毁)底层 ptr 的内存,正如您在下一个片段中看到的那样
class C { deinit { print("I got deinit'd!") } }
struct S { var objectRef:AnyObject? }
func foo() {
let ptr = UnsafeMutablePointer<S>.alloc(1)
let o = C()
let fancy = S(objectRef: o)
ptr.initialize(fancy)
ptr.destroy()
ptr.dealloc(1)
}
(1..<1000).forEach{ i in
foo()
print(i)
}
现在代码按预期执行,所有 保留/释放周期平衡。
我正在尝试转换 Apple 代码示例之一中提供的一些 Objective C 代码:https://developer.apple.com/library/mac/samplecode/avsubtitleswriterOSX/Listings/avsubtitleswriter_SubtitlesTextReader_m.html
目前我得到的结果如下:
func copySampleBuffer() -> CMSampleBuffer? {
var textLength : Int = 0
var sampleSize : Int = 0
if (text != nil) {
textLength = text!.characters.count
sampleSize = text!.lengthOfBytesUsingEncoding(NSUTF16StringEncoding)
}
var sampleData = [UInt8]()
// Append text length
sampleData.append(UInt16(textLength).hiByte())
sampleData.append(UInt16(textLength).loByte())
// Append the text
for char in (text?.utf16)! {
sampleData.append(char.bigEndian.hiByte())
sampleData.append(char.bigEndian.loByte())
}
if (self.forced) {
// TODO
}
let samplePtr = UnsafeMutablePointer<[UInt8]>.alloc(1)
samplePtr.memory = sampleData
var sampleTiming = CMSampleTimingInfo()
sampleTiming.duration = self.timeRange.duration;
sampleTiming.presentationTimeStamp = self.timeRange.start;
sampleTiming.decodeTimeStamp = kCMTimeInvalid;
let formatDescription = copyFormatDescription()
let dataBufferUMP = UnsafeMutablePointer<Optional<CMBlockBuffer>>.alloc(1)
CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, samplePtr, sampleSize, kCFAllocatorMalloc, nil, 0, sampleSize, 0, dataBufferUMP);
let sampleBufferUMP = UnsafeMutablePointer<Optional<CMSampleBuffer>>.alloc(1)
CMSampleBufferCreate(kCFAllocatorDefault, dataBufferUMP.memory, true, nil, nil, formatDescription, 1, 1, &sampleTiming, 1, &sampleSize, sampleBufferUMP);
let sampleBuffer = sampleBufferUMP.memory
sampleBufferUMP.destroy()
sampleBufferUMP.dealloc(1)
dataBufferUMP.destroy()
dataBufferUMP.dealloc(1)
samplePtr.destroy()
//Crash if I call dealloc here
//Error is: error for object 0x10071e400: pointer being freed was not allocated
//samplePtr.dealloc(1)
return sampleBuffer;
}
我想尽可能避免使用 "Unsafe*" 类型,尽管我不确定这里是否可行。我还查看了使用结构,然后以某种方式看到以某种方式打包它,但我看到的示例似乎基于 sizeof,它使用定义的大小,而不是结构的当前大小。这将是我会使用的结构:
struct SubtitleAtom {
var length : UInt16
var text : [UInt16]
var forced : Bool?
}
任何有关最适合此功能的 Swift2 代码的建议将不胜感激。
所以,首先,您的代码使用此模式
class C { deinit { print("I got deinit'd!") } }
struct S { var objectRef:AnyObject? }
func foo() {
let ptr = UnsafeMutablePointer<S>.alloc(1)
let o = C()
let fancy = S(objectRef: o)
ptr.memory = fancy
ptr.destroy() //deinit runs here!
ptr.dealloc(1) //don't leak memory
}
// soon or later this code should crash :-)
(1..<1000).forEach{ i in
foo()
print(i)
}
在操场上试一试,很可能会崩溃 :-)。它出什么问题了?问题是您的 不平衡的保留/释放周期 。如何以安全的方式编写相同的内容?您删除了 dealloc 部分。但尝试在我的代码片段中执行此操作并查看结果。代码再次崩溃:-)。唯一安全的方法是正确初始化和取消初始化(销毁)底层 ptr 的内存,正如您在下一个片段中看到的那样
class C { deinit { print("I got deinit'd!") } }
struct S { var objectRef:AnyObject? }
func foo() {
let ptr = UnsafeMutablePointer<S>.alloc(1)
let o = C()
let fancy = S(objectRef: o)
ptr.initialize(fancy)
ptr.destroy()
ptr.dealloc(1)
}
(1..<1000).forEach{ i in
foo()
print(i)
}
现在代码按预期执行,所有 保留/释放周期平衡。