2009-07-27 7 views
1

Je suis en train de modifier le PTHotKeyLib pour être 64 bits amical, mais j'ai rencontré un problème dans le code que je ne suis pas sûr comment se déplacer. Dans PTHotKeyCenter, la méthode registerHotKey crée une instance EventHotKeyID, puis place l'objet PTHotKey dans l'attribut id. Le code d'origine utilisé un long. Je l'ai converti en NSInteger selon le guide de programmation 64 bits d'Apple.Résolution d'un cast en pointeur à partir d'un entier de taille différente erreur dans la conversion 64 bits

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

Lorsqu'un utilisateur déclenche la touche de raccourci, il appelle la sendCarbonEvent: méthode qui va essayer de tirer l'instance PTHotKey sur EventHotKeyID. Il a travaillé dans la terre 32 bits, mais lors de la compilation contre 64 bits, il donne un « cast à un entier en pointeur de taille différente » avertissement

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

Commutation de x86_64 retour à i386 supprime l'avertissement et tout a été compilé et fonctionne correctement. Sous x86_64, cela cause un problème, et je ne suis pas sûr de savoir comment contourner ce problème. Des suggestions sur la façon de le résoudre?

Répondre

4

La fusion entre des pointeurs et des entiers n'est pas recommandée car elle génère un code non portable.

Ce que vous faites aboutit à ce que C99 définit comme "comportement indéfini". Cela signifie essentiellement que cela pourrait fonctionner, et cela pourrait ne pas fonctionner. Le langage C est célèbre pour vous permettre de faire des choses comme ça parce qu'il suppose implicitement que vous saviez ce que vous faisiez quand vous l'avez tapé et que vous avez le talent fou et des années d'expérience pour savoir quand il est sécuritaire de faire quelque chose comme ceci et quand ce n'est pas.

Il est sûr de dire que c'est l'une de ces fois où il était pas sécuritaire à faire. Le problème, d'après le contexte, est probablement dû à la conversion d'un pointeur 64 bits en variable de taille int. Mac OS X 64 bits ABI est ce que l'on appelle LP64, ce qui signifie que long s et pointer s ont une largeur de 64 bits, et que int s ont une largeur de 32 bits. Donc, en un mot, pendant l'un de vos lancements à int, vous avez coupé les 32 bits supérieurs, ce qui était vraiment important. En regardant les docs, le type id est UInt32. Donc, la réponse courte est que vous ne pouvez pas mettre des pointeurs 64 bits dans des entiers de taille 32 bits.

1

La réponse classique est que vous créez un dictionnaire ou quelque chose, et mettez la clé du dictionnaire dans l'id, et le pointeur dans la valeur, évitant ainsi d'avoir le pointeur réel dans l'id 32bit.

Mais l'avez-vous déjà résolu?

+0

Mettre un pointeur dans une variable trop petite pour contenir un pointeur ne va pas travailler, peu importe ce que les points de pointeur. –

1

Je viens de rencontrer ce même problème avec PTHotKeysLib. Il n'apparaît que dans l'arc x86_64. Pour résoudre, j'ai regardé SGHotKeysLib, qui au lieu d'essayer de faire la distribution comme ci-dessus, stocke à la place une référence au pointeur de 32 bits dans l'objet de 64 bits. Ensuite, lorsque le pointeur de 32 bits est trouvé, il boucle tous les objets de 64 bits (SGHotKey dans le cas présent) pour trouver la référence au pointeur de 32 bits (dans ce cas, EventHotKeyID).)

De plus Référence: https://github.com/secondgear/SGHotKeysLib/blob/master/SGHotKeysLib/SGHotKeyCenter.m

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