2009-07-09 14 views
5

Tôi có một lớp Objective-C chứa cấu trúc kiểu C. Tôi cần gọi hàm C chuyển một con trỏ tới thành viên đối tượng này (thuộc tính a.k.a.). Đối với cuộc sống của tôi, tôi không thể tìm ra cách để có được địa chỉ của cấu trúc C này. Sử dụng toán tử & truyền thống để lấy địa chỉ, tôi nhận được lỗi trình biên dịch LValue.Nhận địa chỉ của thuộc tính Objective-c (là cấu trúc C)

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

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

Kết quả mã sau vào một lỗi biên dịch:

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

MyStruct* p = &(myClass.myStruct); 

Làm thế nào để có được một con trỏ đến myStruct thành viên của đối tượng myClass?

+0

Tôi không biết điều này có hiệu quả không, nhưng hãy thử MyStruct * p = (MyStruct *) & (myClass.myStruct.aNumber); –

+0

Toán tử & toán tử mất một giá trị. Kết quả của một cuộc gọi phương thức là một rvalue. – Chuck

Trả lời

2

MyStruct mystruct là riêng tư trong MyClass, tôi giả sử khi bạn làm myClass.myStruct bạn chỉ đang tham chiếu đến phương thức truy cập được tạo chứ không phải cấu trúc thực tế.

Tôi không nghĩ rằng bạn có thể truy cập biến mẫu (cấu trúc trong trường hợp này) từ bên ngoài vì nó là riêng tư.

+0

Tôi cũng giả định rằng myClass.myStruct đang nhận giá trị được trả về bởi phương thức truy cập - không phải cấu trúc thực tế mà tôi muốn. Giả sử, tôi tạo biến cá thể riêng tư ... làm cách nào tôi có thể đưa con trỏ đến cấu trúc thực tế chứ không phải phương thức truy cập? –

+0

Bạn có thể thử trả về địa chỉ từ một phương thức thành viên (xem câu trả lời của Chuck) hoặc bạn có thể thêm phương thức vào lớp MyClass sẽ gọi C api và chuyển địa chỉ của cấu trúc bí mật. – stefanB

2

Để có được một con trỏ đến biến thể hiện myStruct, bạn cần phải viết một phương thức trả về một con trỏ tới biến mẫu đó.

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

Tôi thực sự nghĩ đây không phải là một ý tưởng hay. Các đối tượng khác không nên biến đổi ivar của đối tượng ra khỏi nó, và đó là điều duy nhất bạn có thể làm với một con trỏ tới cấu trúc mà bạn không thể làm với một bản sao của struct được trả về bởi giá trị.

+2

Trừ khi cấu trúc rất lớn; sử dụng bộ nhớ có khả năng có thể là một vấn đề. –

+0

có thể 'setMyStructPointer:'? –

2

Câu hỏi tự hủy bỏ sự thiếu hiểu biết về ít nhất thuật ngữ.

Một tài sản là một giao diện gồm hai (hoặc một cho readonly) phương pháp được công bố bởi các đối tượng, cụ thể là getter và setter, trong trường hợp này:

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

Nó làm cho không có ý nghĩa để nói về "lấy địa chỉ của một tài sản".

Bạn có thể lấy địa chỉ của biến mẫu (ivar). Trong trường hợp này, bạn có một cái tên là ivar, và bạn có thể lấy địa chỉ của nó với &mystruct trong một phương thức của MyClass. Vì nó được đánh dấu @protected (theo mặc định), bạn có thể lấy địa chỉ của nó trong một lớp con bằng cách sử dụng &self->mystruct. Nếu bạn đánh dấu nó @public, thì bạn có thể lấy địa chỉ của nó bằng cách sử dụng &myobj->mystruct. Đây là một ý tưởng khủng khiếp, và bạn thực sự nên suy nghĩ lại điều này, nhưng bạn có thể làm được.

Nếu bạn chỉ muốn địa chỉ của ivar cho một số mục đích ngắn (ví dụ, nếu MyStruct là lớn), bạn có thể làm điều này, nhưng nó sẽ rất bất thường, và bạn nên viết một cách rõ ràng hơn phương pháp như:

- (MyStruct*) getAddressForSettingMyStruct; 

và nếu nó chỉ là chỉ đọc, thì tốt hơn là sử dụng const MyStruct *.

+12

Câu trả lời này xuất phát từ loại snobbish. Hãy tử tế. – Brenden

2

Thường có lý do khá tốt để làm những gì bài đăng gốc yêu cầu, vì các ứng dụng Mục tiêu-C thường phải làm việc với API C/C++ để đưa con trỏ đến cấu trúc và loại tương tự, nhưng trong ứng dụng Cocoa bạn ' thường sẽ lưu trữ dữ liệu đó trong các lớp Objective-C để quản lý dữ liệu, thu thập trong mảng và từ điển, v.v.

Mặc dù câu hỏi này đã xảy ra một lúc nhưng tôi không thấy câu trả lời rõ ràng, đó là: bạn có thể có phương thức trả về địa chỉ dữ liệu đang sao lưu tài sản của bạn nhưng phương pháp đó không sử dụng " tự "hoặc nó sẽ đi qua accessor và vẫn không hoạt động.

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

Lưu ý rằng tôi đang sử dụng tài sản công bố từ OP, nhưng không tham khảo nó như self.mystruct, mà sẽ tạo ra một lỗi biên dịch (vì đó gọi phương thức getter tổng hợp).

+0

Ví dụ cụ thể tại sao điều này hữu ích - Tôi đang làm một số công việc CoreMIDI và có đối tượng Objective-C gói cấu trúc MIDIPacket cho phép tôi lưu trữ nó trong NSArrays và cũng thêm một số phương thức tiện lợi. Các phương thức API khung trong C yêu cầu một con trỏ const đến cấu trúc, vì vậy lớp khách quan-C của tôi có một phương thức như trên để trả về con trỏ tới thành viên dữ liệu. Đối với các kiểu cấu trúc đơn giản, có thể thích hợp hơn khi sử dụng NSValue, nhưng vì MIDIPacket là động (nó có thể lớn hơn kích thước được khai báo của nó), một lớp trình bao bọc tùy chỉnh là cách để đi. – orpheist

+0

Cảm ơn bạn, giờ đây các lớp con của tôi cuối cùng cũng có thể nhận được tập CGAffineTransform trong lớp cha. –

+0

Tôi đã sử dụng giải pháp của bạn trong câu trả lời cho câu hỏi liên quan cũ: [Objective-C Address of property expression] (http://stackoverflow.com/questions/27468595/objective-c-address-of-property-expression/ 40247837 # 40247837) –