2012-06-28 32 views
7

Tôi có trò chơi đa nền tảng được viết bằng C++. Trong phiên bản mac, mặc dù tôi không có bất kỳ mã obj-c nào, một trong những thư viện tôi sử dụng có vẻ là công cụ tự động phát hành và tôi bị rò rỉ bộ nhớ vì điều đó, vì tôi không tạo NSAutoreleasePool.Làm thế nào để tạo ra một NSAutoreleasePool mà không có Objective-C?

Điều tôi muốn là có thể tạo (và phá hủy) NSAutoreleasePool mà không sử dụng mã obj-c, vì vậy tôi không cần phải tạo tệp .m và thay đổi kịch bản xây dựng của tôi chỉ cho điều đó. Điều đó có thể không? Làm thế nào có thể được thực hiện?

OBS: Được gắn thẻ C và C++, vì giải pháp trong bất kỳ ngôn ngữ nào trong số đó sẽ thực hiện.

+0

Sự cố của bạn có viết bất kỳ mã mục tiêu nào không? Hoặc có các tệp .m trong dự án của bạn khi bạn chỉ muốn .c/.cpp? – Sean

+1

Lưu ý rằng trong khi mã của @ abarnert là giải pháp khả thi, điều này cho biết có lỗi trong thư viện. Không có hàm C hoặc C++ nào nên gọi vào mã ObjC mà không tạo ra một nhóm autorelease. Nếu đây là mã của Apple, bạn nên mở một radar tại bugreport.apple.com. –

+0

@Sean Tôi chỉ muốn các tệp .c/.cpp. Tôi biết tôi có thể loại trừ các tệp đó sang các nền tảng khác, nhưng tôi đang cố tránh điều đó. – fbafelipe

Trả lời

2

Bạn không thể tránh instantiating thời gian chạy Objective-C - nhưng dường như bạn đã có một trong số đó.

Nếu bạn muốn tương tác với thời gian chạy từ C, bạn có thể cho chúng tôi API thời gian chạy Objective-C, như được ghi trong Objective-C Runtime Programming GuideObjective-C Runtime Reference.

Ý tưởng là một cái gì đó như thế này (chưa được kiểm tra):

#include <objc/runtime.h> 
#include <objc/objc-runtime.h> 
id allocAndInitAutoreleasePool() { 
    Class NSAutoreleasePoolClass = objc_getClass("NSAutoreleasePool"); 
    id pool = class_createInstance(NSAutoreleasePoolClass, 0); 
    return objc_msgSend(pool, "init"); 
} 
void drainAutoreleasePool(id pool) { 
    (void)objc_msgSend(pool, "drain"); 
} 

Nếu bạn muốn gọi các chức năng này từ tập tin khác, tất nhiên bạn sẽ phải bao gồm objc/runtime.h đó là tốt. Hoặc, cách khác, bạn có thể bỏ id thành void * trong trả về từ hàm allocAndInit, và lấy một khoảng trống * và đưa trở lại id trong hàm thoát. (Bạn cũng có thể chuyển tiếp cấu trúc objc_object và typedef struct objc_object * id, nhưng tôi tin rằng điều đó không thực sự được đảm bảo đúng định nghĩa.)

Bạn không cần phải chuyển -lobjc trong lệnh liên kết của mình.

Không cần phải nói, có thể ít công việc hơn để chỉ tạo tập lệnh xây dựng của bạn xử lý tệp .m.

+2

Bạn sẽ có thể tải các tệp thời gian chạy bằng mã C thuần túy (không yêu cầu '-lobjc'). Bạn có thể xem ví dụ về điều này tại đây: https://github.com/rnapier/ios5ptl/blob/master/ch20/Runtime/MyMsgSend.c (Tôi không khuyến nghị bạn sử dụng 'myMsgSend()', đó là một minh chứng Tôi chỉ hiển thị một tệp C có thể đồng bộ cho thấy cách tiếp cận này hoạt động.) –

+1

Như một lưu ý phụ, trong khi các tệp '.m' có thể là ok, tôi không khuyên bạn nên giải quyết vấn đề này với'. các tệp mm' ngoại trừ các trình bao bọc rất nhỏ. ObjC++ gây ra rất nhiều vấn đề. Nó là tốt như một miếng keo nhỏ, và đó là một cách tốt để giải quyết vấn đề này (dính vào cuộc gọi trong một hàm '.mm' nhỏ với một tiêu đề C hoặc C++ thuần túy và một @autorelease {} xung quanh cuộc gọi). Nhưng giữ nguyên C++ thuần khiết và ObjC của bạn. –

+0

@RobNapier: Cảm ơn ghi chú trên -lobjc. Tôi sẽ cập nhật câu trả lời. – abarnert

Các vấn đề liên quan