- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在努力初始化 MusicPlayer.h 中找到的 MIDIMetaEvent 结构,头文件定义结构如下:
struct MIDIMetaEvent {
var metaEventType: UInt8
var unused1: UInt8
var unused2: UInt8
var unused3: UInt8
var dataLength: UInt32
var data: (UInt8)
}
在那个“数据”成员之前,这看起来相当简单。那是一个 1 元素的元组定义吗?我可以轻松地初始化所有其他结构元素,但徒劳地尝试将“数据”设置为除单个值以外的任何其他值。在我的代码中,我使用了一个名为 myData 的 UInt8 数组,并尝试像这样初始化结构:
var msg = MIDIMetaEvent(
metaEventType : UInt8(0x7F),
unused1 : UInt8(0),
unused2 : UInt8(0),
unused3 : UInt8(0),
dataLength : UInt32(myData.count),
data : UnsafeBufferPointer<UInt8>(start: UnsafePointer<UInt8>(myData), count:myData.count) )
但编译器对此并不满意,并提示“UnsafeBufferPointer 无法转换为 UInt8”。如果我只是将数据设置为单个值但将 dataLength 设置为大于 1 的值,则生成的 MIDIEventData 显示事件中的第一个值是我卡在“数据”中的值,然后是与“dataLength”字节一致的乱码数据字节.很明显,“数据”被视为某种连续的内存。
那么如何将“数据”元素设置为数组中的 UInt8 元素?
最佳答案
AudioToolbox 框架定义了 MIDIMetaEvent
作为
typedef struct MIDIMetaEvent
{
UInt8 metaEventType;
UInt8 unused1;
UInt8 unused2;
UInt8 unused3;
UInt32 dataLength;
UInt8 data[1];
} MIDIMetaEvent;
哪里data[1]
实际上用作“可变长度数组”。在 (Objective-)C 中,可以只分配一个指向实际需要的尺寸:
MIDIMetaEvent *mep = malloc(sizeof(MIDIMetaEvent) + data.count);
Swift 对指针转换更严格,固定大小的数组被映射到Swift 元组(处理起来可能很麻烦)。
下面的实用程序类展示了如何解决这个问题:
class MyMetaEvent {
private let size: Int
private let mem : UnsafeMutablePointer<UInt8>
let metaEventPtr : UnsafeMutablePointer<MIDIMetaEvent>
init(type: UInt8, data: [UInt8]) {
// Allocate memory of the required size:
size = sizeof(MIDIMetaEvent) + data.count
mem = UnsafeMutablePointer<UInt8>.alloc(size)
// Convert pointer:
metaEventPtr = UnsafeMutablePointer(mem)
// Fill data:
metaEventPtr.memory.metaEventType = type
metaEventPtr.memory.dataLength = UInt32(data.count)
memcpy(mem + 8, data, UInt(data.count))
}
deinit {
// Release the allocated memory:
mem.dealloc(size)
}
}
然后你可以创建一个实例
let me = MyMetaEvent(type: 0x7F, data: myData)
并通过me.metaEventPtr
使用 UnsafePointer<MIDIMetaEvent>
的 Swift 函数争论。
Swift 3/4 更新:
不再可能简单地将指针转换为不同的类型,一定是“反弹”:
class MyMetaEvent {
private let size: Int
private let mem: UnsafeMutablePointer<UInt8>
init(type: UInt8, data: [UInt8]) {
// Allocate memory of the required size:
size = MemoryLayout<MIDIMetaEvent>.size + data.count
mem = UnsafeMutablePointer<UInt8>.allocate(capacity: size)
mem.initialize(to: 0, count: size)
// Fill data:
mem.withMemoryRebound(to: MIDIMetaEvent.self, capacity: 1) { metaEventPtr in
metaEventPtr.pointee.metaEventType = type
metaEventPtr.pointee.dataLength = UInt32(data.count)
memcpy(&metaEventPtr.pointee.data, data, data.count)
}
}
deinit {
// Release the allocated memory:
mem.deallocate(capacity: size)
}
func withMIDIMetaEventPtr(body: (UnsafePointer<MIDIMetaEvent>) -> Void) {
mem.withMemoryRebound(to: MIDIMetaEvent.self, capacity: 1) { metaEventPtr in
body(metaEventPtr)
}
}
}
使用自定义数据创建一个实例:
let me = MyMetaEvent(type: 0x7F, data: ...)
传递给接受 UnsafePointer<MIDIMetaEvent>
的函数参数:
me.withMIDIMetaEventPtr { metaEventPtr in
let status = MusicTrackNewMetaEvent(track, 0, metaEventPtr)
}
关于ios - 初始化 MIDIMetaEvent 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27724055/
我正在努力初始化 MusicPlayer.h 中找到的 MIDIMetaEvent 结构,头文件定义结构如下: struct MIDIMetaEvent { var metaEventType:
在 Swift 之前,MIDIMetaEvent 的数据是通过 data[0]、data[1] 等访问的。要获得拍号,我需要来自数据部分的两个值,这些值被标记为 (UInt8)... 带有括号。但是当
我是一名优秀的程序员,十分优秀!