2017-04-17 89 views
0

我在iOS應用程序上使用C++庫。其中一個功能爲我提供了一個包含C枚舉的std::vector。我想在目標C(而不是對象C++)中使用這些數據,因此我需要將此數組轉換爲等效的Objective C數據結構。我使用的轉換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; 
} 

我的問題是:在維護的方式如何實現這一點?

+0

'ArrayRetValue'的接口是什麼? –

+0

這是問題的一部分。我不確定什麼是合適的。 –

回答

0

經過多方考慮,我決定使用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; 
} 

如果這種解決方案是要在多個枚舉中使用時,選項myEnum(聲明&實現)的創建可以使用宏來完成(以創建模板像解決方案)。

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++代碼中使用此類。

+0

這個解決方案的問題是,每當我使用數組時,我必須將NSNumber重新放入枚舉中(例如在開關情況下)。另外,數組的內容只是MyError的值並不明確。 –