1

我正在努力将PTHotKeyLib修改为 64 位友好,但我在代码中遇到了一个问题,我不确定如何解决。在 PTHotKeyCenter 中, registerHotKey 方法创建一个 EventHotKeyID 实例,然后将 PTHotKey 对象填充到 id 属性中。原代码用了很长。我根据 Apple 的 64 位编程指南将其转换为 NSInteger。

  - (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: 方法,该方法将尝试将 PTHotKey 实例从 EventHotKeyID 中拉出。它在 32 位域中工作,但是在针对 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 切换回 i386 会删除警告,并且所有内容都已编译并正常运行。在 x86_64 下它会导致崩溃,我不确定如何解决这个问题。关于如何解决它的任何建议?

4

3 回答 3

4

不建议在指针和整数之间进行转换,因为它会导致代码不可移植。

您所做的会导致 C99 定义为“未定义的行为”。这基本上意味着它可能会起作用,也可能不会。C 语言以允许你做这样的事情而闻名,因为它隐含地假设你在输入时知道自己在做什么,并且你有神奇的 37337 疯狂技能和多年的经验知道什么时候做类似的事情是安全的这个和什么时候不是。

可以肯定地说,这是不安全的时候之一。

从上下文来看,这个问题可能是由于将一个 64 位指针转换为一个已int调整大小的变量。Mac OS X 64 位 ABI 就是所谓的LP64,这意味着longs 和pointers 是 64 位宽,而ints 是 32 位宽。所以,简而言之,在你的pointer一次int往返铸造中,你砍掉了前 32 位,这恰好非常重要。

查看文档,类型idUInt32. 因此,简短的回答是您不能将 64 位指针放入 32 位大小的整数中。

于 2009-07-27T12:41:01.793 回答
1

经典的答案是您制作字典或其他东西,并将字典的键放在 id 中,将指针放在值中,从而避免实际指针在 32 位 id 中。

但是你解决了吗?

于 2009-08-31T00:28:44.747 回答
1

我刚刚遇到了与 PTHotKeysLib 完全相同的问题。它只出现在 x86_64 架构中。

为了解决这个问题,我查看了 SGHotKeysLib,它没有像上面那样尝试进行强制转换,而是将 32 位指针的引用存储在 64 位对象中。然后当找到 32 位指针时,它会遍历所有 64 位对象(在本例中为 SGHotKey)以查找对 32 位指针的引用(在本例中为 EventHotKeyID。)

进一步参考:https ://github.com/secondgear/SGHotKeysLib/blob/master/SGHotKeysLib/SGHotKeyCenter.m

 for (SGHotKey *thisHotKey in [self allHotKeys]) {
    if ([thisHotKey matchesHotKeyID:hotKeyID]) {
      hotKey = thisHotKey;
      break;
    }
  }
于 2010-11-19T20:47:28.560 回答