2009-07-27 7 views
1

Ich arbeite an der Änderung der PTHotKeyLib, um 64-Bit-freundlich zu sein, aber ich habe ein Problem im Code, ich bin mir nicht sicher wie man herumkommt. In PTHotKeyCenter erstellt die Methode registerHotKey eine EventHotKeyID-Instanz und fügt dann das PTHotKey-Objekt in das ID-Attribut ein. Der ursprüngliche Code wurde lange verwendet. Ich habe es nach Apples 64-Bit-Programmieranleitung in NSInteger umgewandelt.Auflösen von Zeiger auf Zeiger aus Integer unterschiedlicher Größe Fehler in 64-Bit-Konvertierung

- (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 
    } 

Wenn ein Benutzer den Hotkey auslöst, ruft er die sendCarbonEvent: Methode, die die PTHotKey Instanz aus EventHotKeyID ziehen werde es versuchen. Es funktionierte in 32-Bit-Land, aber wenn sie gegen 64-Bit-Kompilierung, gibt es ein „cast Zeiger von Ganzzahl von unterschiedlicher Größe“

- (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 
} 

Wechsel von x86_64 entfernt zurück zu i386 Warnung der Warnung und alles zusammengestellt und läuft einwandfrei. Unter x86_64 verursacht es einen Absturz, und ich bin mir nicht sicher, wie ich dieses Problem umgehen kann. Irgendwelche Vorschläge, wie man es löst?

Antwort

4

Die Umwandlung zwischen Zeigern und Ganzzahlen wird nicht empfohlen, da dies zu nicht tragbarem Code führt.

Was Sie tun, ergibt sich aus dem, was C99 als "undefiniertes Verhalten" definiert. Dies bedeutet im Grunde, dass es funktionieren könnte, und es könnte nicht funktionieren. Die C-Sprache ist berühmt dafür, dass Sie solche Dinge tun können, weil sie implizit davon ausgeht, dass Sie wussten, was Sie taten, als Sie es eintippten und dass Sie die witzige Erfahrung und die jahrelange Erfahrung haben, um zu wissen, wann es sicher ist dies und wenn nicht.

Es ist sicher zu sagen, dies ist einer der Zeiten, als es nicht sicher zu tun war.

Das Problem, aus dem Zusammenhang, liegt wahrscheinlich daran, einen 64-Bit-Zeiger in eine int große Variable umzuwandeln. Mac OS X 64-Bit-ABI ist das, was als LP64 bekannt ist, was bedeutet, dass long s und pointer s 64 Bits breit sind und dass int s 32 Bits breit sind. Kurz gesagt, während einer Ihrer pointer bis int und wieder zurück Castings, Sie abgeschnitten die oberen 32 Bits, die gerade so, wirklich wichtig zu sein.

Mit Blick auf die Dokumentation ist der Typ für idUInt32. Die kurze Antwort lautet also, dass Sie keine 64-Bit-Zeiger auf 32-Bit-Ganzzahlen setzen können.

1

Die klassische Antwort ist, Sie machen ein Wörterbuch oder etwas, und setzen Sie den Schlüssel auf das Wörterbuch in der ID und den Zeiger in den Wert, so dass die tatsächlichen Zeiger in der 32-Bit-ID zu vermeiden.

Aber hast du es schon gelöst?

+0

einen Zeiger in eine Variable zu klein, um einen Zeiger zu halten Putting wird nicht funktionieren, egal, was der Zeiger auf. –

1

Ich lief gerade in genau dieses Problem mit PTHotKeysLib. Es wird nur im x86_64-Arch angezeigt.

Um zu lösen, schaute ich auf SGHotKeysLib, die anstatt zu versuchen, die Besetzung wie oben zu tun, speichert stattdessen einen Verweis auf den 32-Bit-Zeiger in dem 64-Bit-Objekt. Wenn dann der 32-Bit-Zeiger gefunden wird, durchläuft er alle 64-Bit-Objekte (in diesem Fall SGHotKey), um den Verweis auf den 32-Bit-Zeiger (in diesem Fall EventHotKeyID) zu finden.

)

Weitere Referenz: https://github.com/secondgear/SGHotKeysLib/blob/master/SGHotKeysLib/SGHotKeyCenter.m

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