在64位转换中将转换为指针从不同大小的整数错误中解析出来

时间:2009-07-27 06:45:33

标签: cocoa 64-bit macos-carbon

我正在努力将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下它会导致崩溃,我不知道如何解决这个问题。有关如何解决它的任何建议?

3 个答案:

答案 0 :(得分:4)

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

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

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

来自上下文的问题可能是由于将64位指针转换为int大小的变量。 Mac OS X 64位ABI就是所谓的LP64,这意味着longpointer是64位宽,int是32 -bits宽。因此,简而言之,在您的pointerint之一以及再次投射时,您会将前32位切掉,这恰好非常重要。

查看文档时,id的类型为UInt32。所以,简短的回答是你不能将64位指针放入32位大小的整数中。

答案 1 :(得分:1)

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

但你解决了吗?

答案 2 :(得分:1)

我刚刚遇到与PTHotKeysLib相同的问题。它只出现在x86_64 arch。

为了解决这个问题,我查看了SGHotKeysLib,它不是像上面那样尝试进行转换,而是在64位对象中存储对32位指针的引用。然后当找到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;
    }
  }