2011-04-12 58 views
1

我在Objective-C中使用OpenCV靜態庫來執行一些圖像處理,儘管我的應用工作得很好,但在設備本身上它相當慢。大部分的處理事實上可以事先完成,所以我決定我將序列化這些數據,並在應用程序啓動時加載它。使用C++實例變量存檔/序列化Objective-C對象

我需要序列化/歸檔的數據位於CvSeq類型的對象(openCV序列 - 指向值序列的指針)。我基本上想把它保存到文件中,以便稍後加載它。我想我可以做一個類,遵守NSCoding協議和編碼/解碼,從有做到這一點:

@implementation MyObject 

@synthesize point = _point; 
@synthesize description = _description; 

- (id)initWithCoder:(NSCoder *)decoder { 
    if (self = [super init]) { 
     self.point = [decoder decodeObjectForKey:@"point"]; 
     self.description = [decoder decodeObjectForKey:@"description"]; 
    } 
    return self; 
} 

- (void)encodeWithCoder:(NSCoder *)encoder { 
    [encoder encodeObject:self.point forKey:@"point"]; 
    [encoder encodeObject:self.description forKey:@"description"]; 
} 

@end 

但在decodeObjectForKey:和encodeObject:電話我得到的錯誤

error: cannot convert 'objc_object*' to 'CvSeq*' in argument passing 

是否有我的代碼有問題,或者我需要採取另一條路線,以實現與我的對象中的非客觀C實例變量相同的東西?

+0

你也可以發佈頭文件嗎? – Felix 2011-04-12 15:58:36

回答

6

Objective-C的序列化代碼不會知道如何存檔您的C++類。您將需要明確編寫代碼來執行此操作。假設「description」是上述代碼中的CvSeq *,則需要編寫從CvSeq轉換爲Cocoa知道如何存檔的方法。 NSString可能是最容易開始的地方,即使它不是最有效的方案。

NSString* NSStringFromCvSeq(CvSeq* cppObj) 
{ 
    // You have to write this, but at it's simplest it might be something like... 
    return [NSString stringWithFormat: @"%d|%d|%d", cppObj->foo, cppObj->bar, cppObj->baz]; 
} 

CvSeq* NewCvSeqFromNSString(NSString* encodedString) 
{ 
    // You have to write this, but at it's simplest it might be something like... 
    NSScanner* scanner = [NSScanner scannerWithString: encodedString]; 
    [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString: @"|"]]; 
    int foo = [scanner scanInt]; 
    int bar = [scanner scanInt]; 
    int baz = [scanner scanInt]; 

    return new CvSeq(foo, bar, baz); 
} 

- (id)initWithCoder:(NSCoder *)decoder { 
    if (self = [super init]) { 
     self.point = [decoder decodeObjectForKey:@"point"]; 
     self.description = NewCvSeqFromNSString([decoder decodeObjectForKey:@"description"]); 
    } 
    return self; 
} 

- (void)encodeWithCoder:(NSCoder *)encoder { 
    [encoder encodeObject:self.point forKey:@"point"]; 
    [encoder encodeObject: NSStringFromCvSeq(self.description) forKey:@"description"]; 
} 

這裏的關鍵外賣是,可可不知道如何來歸檔任意類型(除已經採用NSCoding的Objective-C型),並沒有某種膠水將永遠封存C++對象「免費」層,因爲C++對象無法採用NSCoding協議。

希望有幫助!

1

而不是自己的編碼/序列化,帶有dataWithBytes方法的NSData類可能會幫助您處理Objective-C世界中的OpenCV Mat數據,如下所示。

NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize() * cvMat.total()]; 

轉移到NSData類後,我們可以將它存儲到文件。

+0

如果你所有的C++對象都是沒有指針類型成員的POD類,或者如果你明確地解引用對象的底層數據(就像你在這裏),這可以工作,但它不是一個通用的編碼解決方案使用Objective-C的C++對象。 – ipmcc 2013-10-09 12:26:17

+0

@ipmcc是否有使用Objective-C編碼C++對象的通用解決方案?如果是這樣,我還沒有找到它。很想找到一個! – livingtech 2014-02-21 16:18:01

+2

@livingtech別屏住呼吸。 – ipmcc 2014-02-21 16:39:57