2009-07-27 3 views
1

PTHotKeyLib을 64 비트 버전으로 수정하려고하는데, 확실하지 않은 코드에서 문제가 발생했습니다 주위를 둘러 보는 법. PTHotKeyCenter에서 registerHotKey 메서드는 EventHotKeyID 인스턴스를 만든 다음 PTHotKey 개체를 id 특성에 채 웁니다. 원래 코드는 오래 사용되었습니다. Apple의 64 비트 프로그래밍 가이드별로 NSInteger로 변환했습니다. EventHotKeyID 밖으로 PTHotKey 인스턴스를 끌어 위해 노력할 것입니다 방법 : 사용자가 바로 가기 키를 트리거 할 때64 비트 변환에서 다른 크기의 정수 오류로 캐스트 변환하기

- (BOOL)registerHotKey:(PTHotKey *)theHotKey { 
    OSStatus error; 
    EventHotKeyID hotKeyID; 
    EventHotKeyRef carbonHotKey; 
    NSValue *key = nil; 

    if ([[self allHotKeys] containsObject:theHotKey]) 
    [self unregisterHotKey:theHotKey]; 

    if (![[theHotKey keyCombo] isValidHotKeyCombo]) 
    return YES; 

    hotKeyID.signature = kHotKeySignature; 
    hotKeyID.id = (NSInteger)theHotKey; 
    ... //Rest is not relevant 
    } 

, 그것은 sendCarbonEvent를 호출합니다. 그것은 32 비트 땅에서 일하지만, 64 비트에 대해 컴파일 할 때, 그것은 경고를 다시 I386에 x86_64의에서 전환

- (OSStatus)sendCarbonEvent:(EventRef)event { 
    OSStatus error; 
    EventHotKeyID hotKeyID; 
    SGHotKey *hotKey; 

    NSAssert(GetEventClass(event) == kEventClassKeyboard, @"Unknown event class"); 

    error = GetEventParameter(event, 
          kEventParamDirectObject, 
          typeEventHotKeyID, 
          nil, 
          sizeof(EventHotKeyID), 
          nil, 
          &hotKeyID); 
    if (error) 
    return error; 

    NSAssert(hotKeyID.signature == kHotKeySignature, @"Invalid hot key id"); 
    NSAssert(hotKeyID.id != 0, @"Invalid hot key id"); 

    hotKey = (SGHotKey *)hotKeyID.id; // warning: cast to pointer from integer of different size 
// Omitting the rest of the code 
} 

경고 "다른 크기의 정수에서 포인터 캐스트의"를 제공 제거하고 모든 컴파일 제대로 실행됩니다. x86_64에서는 크래셔가 발생하며이 문제를 해결하는 방법을 모르겠습니다. 그것을 해결하는 방법에 대한 제안?

답변

4

포인터와 정수 사이의 캐스팅은 이식성이 떨어지는 코드가되므로 권장하지 않습니다.

C99에서 "정의되지 않은 동작"으로 정의한 결과가 나타납니다. 이것은 기본적으로 작동 할 수도 있고 그렇지 않을 수도 있음을 의미합니다. C 언어는 사용자가 입력 할 때 무엇을했는지를 암시하고 암시 적으로 37337 건의 미친 스킬과 수년 간의 경험을 통해 언제 같은 일을하는 것이 안전한지를 알기 때문에이 일을하도록하는 것으로 유명합니다. 이 때와 그렇지 않은 경우.

이것은 이 아니고 일 때 그랬다고 말하기가 안전합니다.

컨텍스트에서 문제는 아마도 int 크기 변수에 64 비트 포인터를 캐스팅했기 때문일 수 있습니다. Mac OS X 64 비트 ABI는 LP64으로 알려져 있습니다. 즉, longpointer은 64 비트 폭이고 int은 32 비트 폭입니다. 즉, pointer ~ int 중 하나와 다시 캐스팅 중 하나가 발생하면 상위 32 비트가 잘 리게되어 매우 중요합니다.

문서를 보면 id의 유형은 UInt32입니다. 그래서, 짧은 대답은 32 비트 정수에 64 비트 포인터를 넣을 수 없다는 것입니다.

1

고전적인 대답은 사전이나 무언가를 만들고, id에있는 사전에 키를 넣고 값에 포인터를 넣어서 32 비트 id에 실제 포인터가 없게하는 것입니다.

하지만 아직 해결하셨습니까?

+0

포인터를 저장하기에 너무 작은 변수에 대한 포인터를 퍼팅 상관없이 포인터 포인트, 작동하지 않을 것입니다. –

1

PTHotKeysLib에서 이와 똑같은 문제가 발생했습니다. x86_64 아치에서만 나타납니다.

해결하려면 SGHotKeysLib을 살펴 보았습니다. SGHotKeysLib는 위의 캐스트를 수행하는 대신 64 비트 객체의 32 비트 포인터에 대한 참조를 저장합니다. 그런 다음 32 비트 포인터가 발견되면 32 비트 포인터 (이 경우 EventHotKeyID)에 대한 참조를 찾기 위해 모든 64 비트 객체 (이 경우 SGHotKey)를 반복합니다.)

또한 참조 : https://github.com/secondgear/SGHotKeysLib/blob/master/SGHotKeysLib/SGHotKeyCenter.m

for (SGHotKey *thisHotKey in [self allHotKeys]) { 
    if ([thisHotKey matchesHotKeyID:hotKeyID]) { 
     hotKey = thisHotKey; 
     break; 
    } 
    }