2016-06-01 10 views
1

아래 코드는 iOS 장비에 연결된 악기에서 MIDI 데이터를 수신합니다. 그것은 32 비트 IOS 장치에서 잘 작동합니다. 64 비트에서 콜백 함수는 모든 이벤트에 대해서도 호출되지만 'pktlist'에 수신 된 데이터는 유효하지 않습니다. 뭐가 잘못 되었 니?이 코드는 iOS 32 비트에서는 작동하지만 64 비트에서는 작동하지 않는 이유는 무엇입니까?

내가 MidiReadProc에서받는 데이터는 항상 64 비트 디바이스에서 동일하고, 길이는 일반적으로 0이 결코 그것을 분명히 잘못된 것입니다 :

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

콜백 기능 :

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; 
CoreMIDI.h에서

추출 : 경우

이 헤더 번역과 관련이있을 수있다, 여기에 번역입니다

에서
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)) 

추출 CoreMIDI.pas (CoreMIDI.h의 번역이 파벨 지리산 슈나 드와 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; 

업데이트 :

코멘트에 다윗에 의해 제안 레코드의 필드 오프셋은 다음과 같습니다.

MIDIPacketList 오프셋 :

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 오프셋 :

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

태그 전쟁을 시작하고 싶지는 않지만 실제로는 firemonkey와는 아무런 관련이 없습니다. –

+0

구조체 정렬이 올바른지 확인 했습니까? –

+0

이것은 FireMonkey와 전혀 관련이 없습니다. 그것은 interop 질문입니다. 나는 FireMonkey에 대해서는 아무 것도 모르지만 interop에 대해서는 많이 알고있다. 내가 FireMonkey 개발자가 아니기 때문에 무시해 주시겠습니까? –

답변

1

의견에서 제안한대로 CoreMIDI.h 헤더 파일을 자세히 살펴 보았습니다. 비록 내가 C 언어로 일한 적이 없지만, 나는이 줄을 발견했다 : MIDIPacket의 정의 위의 #pragma pack(push, 4) (나는이 질문을 추출하기 위해 그것을 추가했다.)은 무엇을해야하는지 명확하게 보여준다.

전체 파일에 대해 {$Align 1}을 설정하는 것이 올바른 해결책이 아닙니다. 대신 두 개의 레코드 (MIDIPacketMIDIPacketList)는 8 바이트 정렬 대신 4 바이트 정렬을 가져야합니다.

-1

C 구조체는 델파이의 포장 레코드로 선언해야합니다. C는 struct의 필드를 정렬하지 않습니다.

+0

이상한 점은 32 비트에서 64 비트에서만 작동한다는 것입니다. – Hans

+0

나는 나의 이전 코멘트를 되 찾는다. 32 비트에서 작동하지 않는 이유는 다른 것입니다. 이제는 32 비트와 64 비트 모두에서 작동합니다. 이제 각 레코드에'packed '를 추가하거나 맨 위에 {$ Align 1}을 추가하는 것과 다른 점이 있다면 질문입니다 ... – Hans

+0

답을 정답으로 표시하게되어 기쁩니다. 그러나 Delphi에 포함 된 프레임 워크 헤더의 26 개 번역 중 '포장 된'또는 Align1을 사용하지 않는 것은 이상한 일입니다. – Hans