swift

时间:2016-01-13 20:35:39

标签: swift coremidi

我试图将一些C代码转换为swift。 (为什么? - 如果你问的话,在OS-X中使用CoreMIDI)

C代码就像这样

void printPacketInfo(const MIDIPacket* packet) {
   int i;
   for (i=0; i<packet->length; i++) {
      printf("%d ", packet->data[i]);
   }
 }

MIDIPacket的定义如下

struct MIDIPacket
 {
    MIDITimeStamp           timeStamp;
    UInt16                  length;
    Byte                    data[256];
 };

My Swift就像这样

func printPacketInfo(packet: UnsafeMutablePointer<MIDIPacket>){
    // print some things
    print("length", packet.memory.length)
    print("time", packet.memory.timeStamp)
    print("data[0]", packet.memory.data.1)
    for i in 0 ..< packet.memory.length {
      print("data", i, packet.memory.data[i])
    }
  }

但这会产生编译错误

  

错误:键入&#39;(UInt8,UInt8,..剪切.. UInt8,UInt8,UInt8)&#39;      没有下标成员

那么如何取消引用固定大小数组的第I个元素?

4 个答案:

答案 0 :(得分:3)

在你的情况下你可以尝试使用这样的东西......

// this is tuple with 8 Int values, in your case with 256  Byte (UInt8 ??) values
var t = (1,2,3,4,5,6,7,8)
t.0
t.1
// ....
t.7
func arrayFromTuple<T,R>(tuple:T) -> [R] {
    let reflection = Mirror(reflecting: tuple)
    var arr : [R] = []
    for i in reflection.children {
        // better will be to throw an Error if i.value is not R
        arr.append(i.value as! R)
    }
    return arr
}

let arr:[Int] = arrayFromTuple(t)
print(arr) // [1, 2, 3, 4, 5, 6, 7, 8]

...

let t2 = ("alfa","beta","gama")
let arr2:[String] = arrayFromTuple(t2)
arr2[1] // "beta"

答案 1 :(得分:1)

错误消息是一个提示:它显示MIDIPacket.data不是作为数组导入,而是作为元组导入。 (是的,这就是所有固定长度数组在Swift中导入的方式。)您似乎在前一行注意到了这一点:

print("data[0]", packet.memory.data.1)

Swift中的元组是非常静态的,因此没有办法动态访问元组元素。因此,在某种意义上,打印数据包的唯一“安全”或惯用方式(以你暗示的方式)将是256行代码(或者高达256行,因为数据包的length字段告诉我们你什么时候可以安全停止):

print("data[1]", packet.memory.data.2)
print("data[2]", packet.memory.data.3)
print("data[3]", packet.memory.data.4)
/// ...
print("data[254]", packet.memory.data.255)
print("data[255]", packet.memory.data.256)

显然,这不是一个好的解决方案。根据用户3441734的回答,使用反射是一种(繁琐的)替代方案。根据您自己的答案(通过jckarter),不安全的内存访问是另一个(但正如API的名称所说,它“不安全”)。当然,您始终可以通过(Obj)C。

处理数据包

如果您需要执行除打印数据包之外的操作,可以扩展基于UnsafePointer的解决方案,将其转换为如下数组:

extension MIDIPacket {
    var dataBytes: [UInt8] {
        mutating get {
            return withUnsafePointer(&data) { tuplePointer in
                let elementPointer = UnsafePointer<UInt8>(tuplePointer)
                return (0..<Int(length)).map { elementPointer[$0] }
            }
        }
    }
}

请注意,这会使用数据包的现有length属性来公开一个数组,该数组的有效字节数与数据包声称的数量相同(而不是用零填充256元素数组的其余部分)。但这确实会分配内存,因此对于您可能使用CoreMIDI的各种实时运行条件可能不太好。

答案 2 :(得分:1)

这是https://gist.github.com/jckarter/ec630221890c39e3f8b9

建议的
using (MySqlCommand cmd = 
       new MySqlCommand("TRUNCATE TABLE myproject.words; TRUNCATE TABLE myproject.other;"  
       , cnn))

这是可怕的 - 我希望编译器把这个废话变成一些好的代码

答案 3 :(得分:0)

应该这样:     for i in 0 ..< packet.memory.length

这是吗?     for i in 0 ..< packet.memory.data.length