2016-06-01 13 views
1

Der folgende Code empfängt MIDI-Daten von einem Musikinstrument, das mit dem iOS-Gerät verbunden ist. Es funktioniert gut auf einem 32-Bit-iOS-Gerät. Bei 64 Bit wird die Callback-Funktion auch für jedes Event aufgerufen, aber die in 'pktlist' empfangenen Daten sind ungültig. Was ist falsch?Warum funktioniert dieser Code unter iOS 32 Bit, aber nicht unter 64 Bit?

Die Daten, die ich in MidiReadProc erhalten ist immer das gleiche auf einem 64-Bit-Gerät, und es ist eindeutig falsch, da die Länge würde normalerweise nie 0 sein:

pktlist^.numPackets = 1 
lPacket.MIDItimestamp=$E4FE000100000961 
lPacket.length=$0000 
lPacket.data[0]=$00 

Die Callback-Funktion:

procedure MidiReadProc(pktlist: MIDIPacketListRef; refCon, connRefCon: Pointer); cdecl; 
var 
    lPacket: MIDIPacket; 
    lPacketRef: MIDIPacketRef; 
    j: Integer; 
    lPtr: ^Byte; 
begin 
    lPacketRef := MIDIPacketRef(@(pktlist^.Packet[0])); 
    for j := 0 to pktlist^.numPackets-1 do 
    begin 
    lPacket := lPacketRef^; 
    if (lPacket.length > 0) and (lPacket.data[0] <> $F0) then 
     //handle data here 

    //translation of the MIDIPacketNext Macro: 
    lPtr := @lPacketRef^.data[lPacketRef^.length]; 
    lPacketRef := MIDIPacketRef((UInt64(lPtr) + 3) and (not 3)); 
    end; 
end; 

Falls es in die Header-Übersetzung zusammenhängen könnte, ist hier die Übersetzung:

Auszug aus CoreMIDI.h:

012.351.
typedef UInt64 MIDITimeStamp; 

#pragma pack(push, 4) 
struct MIDIPacket 
{ 
    MIDITimeStamp  timeStamp; 
    UInt16    length; 
    Byte    data[256]; 
}; 
typedef struct MIDIPacket   MIDIPacket; 

struct MIDIPacketList 
{ 
    UInt32    numPackets; 
    MIDIPacket   packet[1]; 
}; 
typedef struct MIDIPacketList MIDIPacketList; 
#pragma pack(pop) 

typedef void 
(*MIDIReadProc)(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon); 


#if TARGET_CPU_ARM || TARGET_CPU_ARM64 
// MIDIPacket must be 4-byte aligned 
#define MIDIPacketNext(pkt) ((MIDIPacket *)(((uintptr_t)(&(pkt)->data[(pkt)->length]) + 3) & ~3)) 

Auszug aus CoreMIDI.pas (die Übersetzung von CoreMIDI.h von Pavel Jiri Strnad gemacht und is available here):

MIDITimeStamp = UInt64; 

MIDIPacket = record 
    timeStamp: MIDITimeStamp; 
    length: UInt16; 
    data: array [0..255] of Byte; 
end; 
MIDIPacketRef = ^MIDIPacket; 

MIDIPacketList = record 
    numPackets: UInt32; 
    packet: array [0..0] of MIDIPacket; 
end; 
MIDIPacketListRef = ^MIDIPacketList; 

MIDIReadProc = procedure (pktlist: MIDIPacketListRef; readProcRefCon: pointer; srcConnRefCon: pointer); cdecl; 

Update:

Wie in den Kommentaren von David vorgeschlagen Hier sind die Feldversätze der Datensätze:

MIDIPacketList Offsets:

64 bit Align 8: numPackets=0 packet=8 <- this was the one causing problems 
64 bit Align 1: numPackets=0 packet=4 
32 bit Align 8: numPackets=0 packet=4 
32 bit Align 1: numPackets=0 packet=4 

MIDIPacket Offsets:

64 bit Align 8: timeStamp=0 length=8 data=10 
64 bit Align 1: timeStamp=0 length=8 data=10 
32 bit Align 8: timeStamp=0 length=8 data=10 
32 bit Align 1: timeStamp=0 length=8 data=10 
+1

Ich möchte nicht einen Tag Krieg starten, aber das hat wirklich nichts mit Firefemonkey zu tun. –

+0

Haben Sie überprüft, ob die Strukturausrichtung korrekt ist? –

+0

Das hat absolut nichts mit FireMonkey zu tun. Es ist eine Interop-Frage. Ich weiß nichts über FireMonkey, aber viel über Interop. Möchtest du, dass ich es ignoriere, weil ich kein FireMonkey-Entwickler bin? –

Antwort

1

Wie in den Kommentaren vorgeschlagen, schaute ich weiter in die Header-Datei. Obwohl ich nie mit irgendwelchen C-Sprachen gearbeitet habe, habe ich diese Zeile entdeckt: #pragma pack(push, 4) über der Definition von MIDIPacket (ich habe es jetzt hinzugefügt, um in der Frage zu extrahieren), was deutlich zeigt, was zu tun ist.

Einstellung {$Align 1} für die gesamte Datei war nicht die richtige Lösung. Stattdessen sollten nur die zwei Datensätze (MIDIPacket und MIDIPacketList) 4-Byte-Alignment statt 8-Byte-Alignment haben.

-1

C-Struktur muss als gepackte Datensatz in delphi deklariert werden. C richtet Felder in Strukturen nicht aus.

+0

Das seltsame ist, dass dies nicht auf 32 Bit funktioniert, nur auf 64 Bit. – Hans

+0

Ich nehme meinen vorherigen Kommentar zurück. Der Grund, warum es bei 32 Bit nicht funktionierte, war etwas anderes. Es funktioniert jetzt sowohl mit 32 Bit als auch mit 64 Bit. Die Frage ist nun, ob es einen Unterschied zwischen dem Hinzufügen von "gepackt" zu jedem Datensatz oder dem Hinzufügen von {$ Align 1} an der Spitze gibt ... – Hans

+0

Ich würde gerne Ihre Antwort als die richtige Antwort markieren. Allerdings finde ich es seltsam, dass keine der 26 Übersetzungen von Framework-Headern, die in Delphi enthalten sind, weder 'packed' noch Align1 verwendet. – Hans

Verwandte Themen