【问题标题】:How to covert a c++ enum vector to an equivalent Objective C array/vector?如何将 C++ 枚举向量转换为等效的 Objective C 数组/向量?
【发布时间】:2017-04-17 19:46:50
【问题描述】:

我在 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;
}

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

【问题讨论】:

  • ArrayRetValue的接口是什么?
  • 这是问题的一部分。我不确定什么是合适的。

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


【解决方案1】:

在 .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++ 代码中使用此类。

【讨论】:

  • 这个解决方案的问题是,每当我使用数组时,我都必须将 NSNumber 转换回枚举(例如在 switch 案例中)。另外,数组的内容只是 MyError 的值也不是很明确。
【解决方案2】:

经过深思熟虑,我决定使用 NSArray 和泛型的组合。通过这种方式,我可以明确地了解数据,并且在使用 Objective-C 对象时不必担心 C 数组可能存在内存泄漏。

为了实现这一点,我必须为我的 C 枚举创建一个 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(声明和实现)(以创建类似模板的解决方案)。

【讨论】:

    猜你喜欢
    • 2017-10-10
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 2022-12-31
    • 2023-04-07
    • 1970-01-01
    • 2019-07-17
    • 2015-02-14
    相关资源
    最近更新 更多