【问题标题】:Get the address of an Objective-c property (which is a C struct)获取 Objective-c 属性的地址(这是一个 C 结构)
【发布时间】:2009-07-09 05:43:47
【问题描述】:

我有一个包含 C 风格结构的 Objective-C 类。我需要调用一个 C 函数,将指针传递给该对象成员(也称为属性)。对于我的生活,我无法弄清楚如何获取这个 C 结构的地址。使用传统的& 运算符来获取地址,我得到一个 LValue 编译器错误。

typedef struct _myStruct
{
   int aNumber;
}MyStruct, *pMyStruct;

@interface MyClass : NSObject {
    MyStruct mystruct;
}
@property (readwrite) MyStruct myStruct;
@end

以下代码导致编译器错误:

MyClass* myClass = [[MyClass alloc] init];

MyStruct* p = &(myClass.myStruct);

如何获得指向myClass 对象的myStruct 成员的指针?

【问题讨论】:

  • 我不知道这是否可行,但请尝试 MyStruct* p = (MyStruct*)&(myClass.myStruct.aNumber);
  • & 运算符采用左值。方法调用的结果是一个右值。

标签: objective-c lvalue declared-property address-operator


【解决方案1】:

考虑到 Objective-C 应用程序通常必须使用 C/C++ API 来获取指向结构和类似类型的指针,因此通常有很好的理由去做原始帖子所要求的事情,但在 Cocoa 应用程序中,您将经常希望将此类数据存储在 Objective-C 类中,用于数据管理、数组和字典中的收集等。

虽然这个问题已经提出了一段时间,但我没有看到明确的答案,即:您可以有一个方法返回支持您的属性的数据的地址,但在该方法中不要使用“self " 否则它会通过访问器仍然无法工作。

- (const MyStruct*) getMyStructPtr
{
    return &mystruct;
}

请注意,我使用的是 OP 中声明的属性,但没有将其引用为 self.mystruct,这会产生编译器错误(因为这会调用合成的 getter 方法)。

【讨论】:

  • 作为一个具体的例子,为什么这很有用 - 我正在做一些 CoreMIDI 工作,并且有一个包装 MIDIPacket 结构的 Objective-C 对象,它让我可以将它存储在 NSArrays 中并添加一些方便的方法。 C 中的框架 API 方法需要一个指向结构的 const 指针,所以我的 Objective-C 类有一个类似上面的方法来返回指向数据成员的指针。对于简单的结构类型,最好只使用 NSValue,但由于 MIDIPacket 是动态的(它可能大于其声明的大小),因此可以使用自定义包装类。
  • 谢谢,现在我的子类终于可以拿到父类中设置的CGAffineTransform了。
  • 我在回答一个旧的相关问题时使用了您的解决方案:Objective-C Address of property expression
【解决方案2】:

MyStruct mystructMyClass 中是私有的,我假设当您执行myClass.myStruct 时,您只是指的是生成的访问器方法而不是实际的结构。

我认为您不能从外部访问实例变量(在这种情况下为结构),因为它是私有的。

【讨论】:

  • 我也假设 myClass.myStruct 正在获取访问器方法返回的值 - 而不是我想要的实际结构。假设,我将实例变量设为私有......我怎样才能获得指向实际结构而不是访问器方法的指针?
  • 您可以尝试从成员方法返回地址(请参阅 Chuck 的回答),或者您可以向 MyClass 类添加方法,该方法将调用 C api 并传递 mystruct 结构的地址。
【解决方案3】:

要获得指向 myStruct 实例变量的指针,您需要编写一个返回指向该实例变量的指针的方法。

- (void)getMyStructPointer:(MyStruct **)outStruct {
    *outstruct = &myStruct;
}

不过,我真的不认为这是一个好主意。其他对象不应该从它下面改变该对象的 ivar,这是您唯一可以使用指向该结构的指针做的事情,而您无法使用由值返回的结构的副本。

【讨论】:

  • 除非结构体很大;内存使用可能是一个问题。
  • 也许是setMyStructPointer:?
【解决方案4】:

问题本身表明至少对术语缺乏理解。

属性是由对象公开的两个(或一个只读)方法组成的接口,即 getter 和 setter 方法,在这种情况下:

- (MyStruct) myStruct;
- (void) setMyStruct: (MyStruct) newMyStruct;

谈论“获取财产地址”是没有意义的。

您可以获取实例变量 (ivar) 的地址。在这种情况下,您有一个名为 mystruct 的 ivar,您可以在 MyClass 的方法中使用 &mystruct 获取它的地址。由于它被标记为@protected(默认情况下),因此您可以使用&self->mystruct 在子类中获取它的地址。如果您将其标记为@public,那么您可以使用&myobj->mystruct 获取它的地址。这是一个糟糕的想法,你真的应该重新考虑一下,但你可以做到。

如果您只是想将 ivar 的地址用于某些短期目的(例如,如果 MyStruct 很大),您可以这样做,但这很不寻常,您最好编写一个显式命名的方法喜欢:

- (MyStruct*) getAddressForSettingMyStruct;

如果它只是只读的,最好使用 const MyStruct*。

【讨论】:

  • 这个答案有点势利。做个好人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多