【问题标题】:Archive/Serialize Objective-C Object with C++ Instance Variables使用 C++ 实例变量归档/序列化 Objective-C 对象
【发布时间】:2011-04-12 15:33:04
【问题描述】:

我在 Objective-C 中使用 OpenCV 静态库来进行一些图像处理,虽然我的应用程序运行良好,但在设备本身上却相当慢。大部分处理实际上可以预先完成,所以我决定序列化这些数据,并在应用启动时加载它。

我需要序列化/存档的数据位于 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 实例变量的情况下实现相同的目标?

【问题讨论】:

  • 可以把头文件也发一下吗?

标签: c++ objective-c serialization opencv archiving


【解决方案1】:

Objective-C 的序列化代码不会知道如何归档您的 C++ 类。您将需要显式地编写代码来做到这一点。假设“描述”是上述代码中的 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"];
}

这里的关键点是 Cocoa 不知道如何归档任意类型(除了已经采用 NSCoding 的 Objective-C 类型),并且在没有某种粘合层的情况下永远不会“免费”归档 C++ 对象,因为C++ 对象无法采用 NSCoding 协议。

希望有帮助!

【讨论】:

    【解决方案2】:

    具有 dataWithBytes 方法的 NSData 类可以帮助您处理 Objective-C 世界中的 OpenCV Mat 数据,而不是自己的编码/序列化。

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

    转入 NSData 类后,我们可以将其存储到文件中。

    【讨论】:

    • 如果您的所有 C++ 对象都是没有任何指针类型成员的 POD 类,或者如果您明确取消引用对象的基础数据(就像您在这里一样),这可以工作,但它不是使用 Objective-C 编码 C++ 对象的通用解决方案。
    • @ipmcc 是否有使用 Objective-C 对 C++ 对象进行编码的通用解决方案?如果是这样,我还没有找到它。很想找一个!!!
    • @livingtech 不要屏住呼吸。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多