如何将c ++枚举向量转换为等效的Objective C数组/向量?

时间:2017-04-17 19:46:50

标签: c++ ios objective-c arrays enums

我在iOS应用上使用C ++库。其中一个函数为我提供了一个包含C枚举的std::vector。我想在Objective C(而不是Object C ++)中使用这些数据,因此我需要将此数组转换为等效的Objective C数据结构。我正在使用一个将C ++转换为Objective C的桥接类。

我的代码看起来有点像:

typedef enum 
{  
  Error0 = 0,
  Error1 = 1,
  Error2 = 2
} MyError;

class ListenerImpl : public Listener
{
public:
    ListenerImpl(Listener* listener) : _listener(listener) {}
    void onError(std::vector<MyError> errors) override
    {
        // Calling Objective C listener (listener class should not be using Objective C++)
        [_listener onError:convertToObjC(errors)];
    }

    void handleError(MyError error, int someExtraData) {
        // Error values are returned back to C++ so if any mapping is to be used it needs to be bi-directional.
    }
private:

    // The question is how to implement this function and what is a good return value here.
    ArrayRetValue convertToObjC(std::vector<MyError> & errors) 
    { 
        // Not sure how to accomplish this
    }
    __weak Listener* _listener;
}

我的问题是:如何以可维护的方式实现这一点?

2 个答案:

答案 0 :(得分:0)

在.h文件中:

#if __OBJC__
typedef NSArray *ArrayRetValue;
#else
typedef void *ArrayRetValue;
#endif

在.mm文件中(你需要它来混合C ++和Obj-C代码):

NSMutableArray * ListenerImpl::convertToObjC(std::vector<MyError> & errors) 
{
    NSMutableArray *objCErrors = [NSMutableArray arrayWithCapacity:errors.size()];
    for (auto error: errors) {
        [objCErrors addObject:[NSNumber numberWithInt:error]];
    }
    return objCErrors;
}

此外,您还需要将onError函数移动到.mm文件,否则您将无法在C ++代码中使用此类。

答案 1 :(得分:0)

经过深思熟虑,我决定使用NSArray和仿制药的组合。通过这种方式,我可以明确地了解数据,因为我使用的是Objective-C对象,所以我不必担心C数组可能会发生内存泄漏。

为了实现这一点,我必须为我的C enum创建一个Objective-C等效对象(因为NSArray需要一个类型)。因此我创建了ErrorEnumObj

以下是完整的解决方案:

typedef enum 
{  
  Error0 = 0,
  Error1 = 1,
  Error2 = 2
} MyError;

@interface ErrorEnumObj : NSObject

@property (nonatomic) int intValue;

+ (instancetype) objWithEnum:(MyError) myError;
- (MyError) getEnumValue;

@end 

@implementation ErrorEnumObj

+ (instancetype) objWithEnum:(MyError) error
{
    ErrorEnumObj * obj = [ErrorEnumObj new];
    obj.intValue = (int)error;
    return obj;
}

- (MyError) getEnumValue
{
    return (MyError)self.intValue;
}

@end

class ListenerImpl : public Listener
{
public:
    ListenerImpl(Listener* listener) : _listener(listener) {}
    void onError(std::vector<MyError> errors) override
    {
        NSMutableArray<ErrorEnumObj *> * array = [NSMutableArray<ErrorEnumObj *> new]; 
        for (auto&& myError : errors)
        {
            [array addObject:[ErrorEnumObj objWithEnum:myError]];
        }
        [_listener onError:array];
    }

private:
    __weak Listener* _listener;
}

如果要在多个枚举上使用这种解决方案,可以使用宏来创建EnumObj(声明和实现)(以创建类似解决方案的模板)。