C库的Objective C包装器:包装返回Obj-C对象的调用

时间:2013-11-21 02:48:09

标签: objective-c c automatic-ref-counting wrapper

我正在尝试在Objective C中包装一个C库,这样我就可以让ARC处理C对象的创建和销毁。这是我的问题...如何包装返回C对象的C库函数,例如:

thing *getRelatedThing(thing *otherFoo);

我知道Objective-C中的方法签名需要是:

@interface Thing {
    @private
    thing *_myThing;
}

- (Thing *)getRelatedThing;

@end

Thing转到thing*很容易,但我无法找出实现反向查找的最佳方法。到目前为止,我对我提出的想法并不感到兴奋:

  1. 修改C库,将指针添加回Objective-C对象。
  2. 创建一个将C对象映射到Objective-C对象的全局字典。
  3. 还有其他想法吗?

    这是我正在努力实现的更多背景:

    C库

    thing *newThing();
    void deleteThing(thing *ptr);
    void doSomething(thing *ptr);
    thing *getRelatedThing(thing *otherFoo);
    

    Objective-C标头

    @interface Thing {
        @private
        thing *_myThing;
    }
    
    - (id)init;
    - (void)doSomething;
    - (Thing *)getRelatedThing;
    
    @end
    

    ** Objective-C实施

    @implementation Thing
    
    - (id)init
    {
        if(self = [super init]) {
            _myThing = newThing();
            if(!_myThing) return nil;
        }
        return self;
    }
    
    - (void)dealloc
    {
        deleteThing(_myThing);
    }
    
    - (void)doSomething
    {
        doSomething(_myThing);
    }
    
    - (Thing *)getRelatedThing
    {
        thing *otherThing = getRelatedThing(_myThing);
        return nil; // Need to return a Thing object instead
    }
    
    @end
    

1 个答案:

答案 0 :(得分:1)

之前我做过类似的事情,我正在使用第一种方式。 (C ++库本身支持void *用户上下文指针,因此我不需要添加它)

但在决定走哪条路之前,你需要弄清楚它是如何起作用的。

  1. 内存管理如何运作?你的ObjC对象是否拥有对C对象或其他方式的强引用?确保不创建保留周期。

  2. ObjC对象和C对象之间是一对一关系吗?如果ObjC对象只是一个纯包装器,那么每次需要将C对象转换为ObjC对象时,都可以新建一个新的包装器。由于它们本身没有任何有用的信息,因此可以毫无问题地丢弃和重新创建它们。


  3. 一种可能的解决方案

    除了您的公开标题

    // private header
    @interface Thing ()
    
    - (id)initWithThing:(thing *)thing;
    
    @end
    
    @implementation Thing
    
    // in addition to your other methods
    
    - (id)initWithThing:(thing *)thing 
    {
        if(self = [super init]) {
            _myThing = thing;
            if(!_myThing) return nil;
        }
        return self;
    }
    
    - (id)init
    {
        return [self initWithThing:newThing()];
    }
    
    - (Thing *)getRelatedThing
    {
        thing *otherThing = getRelatedThing(_myThing); // assume caller responds to release otherThing
        return [[Thing alloc] initWithThing:otherThing];
    }
    
    @end