Здесь нет необходимости в обертке. Объекты Obj C могут без проблем проходить через C и даже поддерживать AR C. Я собираюсь немного изменить стиль, чтобы соответствовать CoreFoundation. Я напишу это снова, чтобы показать, как это будет выглядеть, не подвергая вызывающую сторону CoreFoundation.
main. c
int main(int argc, const char * argv[])
{
// "Ref" means pointer. ...Create() means you must Release it.
TestObjectRef t = TestObjectCreate();
// Call your function
TestObjectPrintHello(t);
// And release it.
CFRelease(t);
return 0;
}
testobject.h
#ifndef testobject_h
#define testobject_h
#import <CoreFoundation/CoreFoundation.h>
// Only define the ObjC part in ObjC
#ifdef __OBJC__
#import <Foundation/Foundation.h>
@interface TestObject : NSObject
- (void) printHello;
@end
#endif
// This is the "void *" of CoreFoundation, but it lets the compiler know this
// this is a bridged ObjC object. This is the standard CF way of naming pointer types.
typedef CFTypeRef TestObjectRef;
// This is the standard CF way of naming functions. "Create" means you need to release it.
TestObjectRef TestObjectCreate(void);
// CF functions always start with their class
void TestObjectPrintHello(TestObjectRef t);
#endif /* testobject_h */
testobject.m
#import "testobject.h"
@implementation TestObject
- (void)printHello
{
printf("HELLO!\n");
}
@end
// ARC is no problem. We just need to tell ARC that we intend to keep an extra retain.
TestObjectRef TestObjectCreate(void) {
return CFBridgingRetain([TestObject new]);
}
// And we can get back to ObjC using `__bridge`
void TestObjectPrintHello(TestObjectRef t) {
[(__bridge TestObject *)t printHello];
}
Это решение пропускает CoreFoundation.h вызывающей стороне и навязывает имя в стиле CF. Мне это очень нравится в моих системах. Но иногда я работаю над существующей кроссплатформенной системой C, и вы хотите скрыть эти детали. Поэтому, если бы я пытался соответствовать стилю в вашем примере, я сделал бы это следующим образом:
main. c
int main(int argc, const char * argv[])
{
TestObjectC *t = newTestObject();
TestObject_printHello(t);
TestObject_release(t); // Still need memory management. Can't avoid that.
return 0;
}
testobject.h
#ifndef testobject_h
#define testobject_h
#ifdef __OBJC__
#import <Foundation/Foundation.h>
@interface TestObject : NSObject
- (void) printHello;
@end
#endif
typedef const void TestObjectC; // 'const void *' is more CF-like, but either is fine
TestObjectC* newTestObject(void);
void TestObject_printHello(TestObjectC *t);
void TestObject_release(TestObjectC *t);
#endif /* testobject_h */
testobject.m
#import "testobject.h"
@implementation TestObject
- (void)printHello
{
printf("HELLO!\n");
}
@end
TestObjectC* newTestObject(void) {
return CFBridgingRetain([TestObject new]);
}
void TestObject_printHello(TestObjectC *t) {
[(__bridge TestObject *)t printHello];
}
void TestObject_release(TestObjectC *t) {
CFRelease(t);
}