gpt4 book ai didi

objective-c - 有没有办法将 Protocol Buffer 包装到 Objective-C 中并仍然利用继承?

转载 作者:太空狗 更新时间:2023-10-30 03:45:56 24 4
gpt4 key购买 nike

我想在 iOS 项目中使用 Protocol Buffers。我试图避免将整个项目变成 Objective-C++ 的惨败,所以我想将 C++ protobuf 类包装到 Objective-C 类中。我有几十个 protobuf 消息,虽然我一次成功地完成了一个类,但理想情况下我想使用继承来最小化重复代码。我是 Objective-C 的新手,我已经 10 年没有使用我对 C++ 知之甚少的东西了,所以这主要是一次沮丧的练习。下面是我如何包装单个消息的示例。

代码

.proto:

message MessageA {
optional string value = 1;
}

MessageAWrapper.h:

#import <Foundation/Foundation.h>

@interface MessageAWrapper : NSObject

@property (nonatomic) NSString *value;

+ (id)fromString:(NSString *)string;
- (NSString *)serialize;

@end

MessageAWrapper.mm:

#import "MessageA.h"
#import "message.pb.h"

@interface MessageAWrapper ()

@property (nonatomic) MessageA *message;

@end

@implementation MessageAWrapper

- (id)init
{
self = [super init];
if (self) {
self.message = new MessageA();
}
return self;
}

- (void)dealloc {
delete self.message;
self.message = NULL;
}

- (NSString *)value {
return [NSString stringWithUTF8String:self.message->value().c_str()];
}

- (void)setValue:(NSString *)value {
self.message->set_value([value UTF8String]);
}

- (NSString *)serialize {
std::string output;
self.message->SerializeToString(&output);
return [NSString stringWithUTF8String:output.c_str()];
}

+ (id)fromString:(NSString *)string {
MessageA *message = new MessageA();
message->ParseFromString([string UTF8String]);

MessageAWrapper *wrapper = [[MessageAWrapper alloc] init];
wrapper.message = message;
return wrapper;
}

@end

目标

这里有很多代码会重复几十次,其中唯一的变化是包装类类型(init, dealloc, serialize , fromString), 所以理想情况下我想把它放在父 ProtobufMesssage 类上。不幸的是,我没有成功完成这项工作,因为我找不到让父类知道其子类正在使用的类的方法,这在 init 中是必需的fromString.

我尝试过的事情

  • 结构
  • 模板类
  • 无效*

我遇到的障碍

  • 找不到一种方法来存储对类/类型的引用
  • .h 文件中不能有任何 C++ 头文件或代码(因为这要求整个项目都是 Objective-C++)
  • 很难保持对 protobuf 消息父级(MessageMessageLite)的引用,因为它们是抽象的

正如我所说,我对 C++ 或 Objective-C 知之甚少;我的大部分经验都是使用更高级的语言,如 Python 和 Java(尽管我主要了解基本的 C 语言,如指针)。

这甚至不可能吗?我是在处理错误还是遗漏了一些明显的东西?任何帮助将非常感激。谢谢。

最佳答案

我对 C++ 了解不多,但你不能将 Objective-C 属性声明为 Message * 吗?

您已经通过在 .mm 文件中声明属性将 C++ 代码与 header 分开,您将遇到的问题是编译器命名的实例方法(value()set_value()) 并且仅是子类的有效方法。使用 Reflection 类按名称获取和设置字段可能会有所帮助。以下是 Google 的 message.h 的摘录,展示了这一点:

Message* foo = new Foo;
const Descriptor* descriptor = foo->GetDescriptor();

const FieldDescriptor* text_field = descriptor->FindFieldByName("text");
assert(text_field != NULL);
assert(text_field->type() == FieldDescriptor::TYPE_STRING);
assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL);

const Reflection* reflection = foo->GetReflection();
assert(reflection->GetString(foo, text_field) == "Hello World!");

您可以创建 Objective-C -objectForKey:-setObject:forKey: 实例方法来进行类型检查并获取或设置值(令人困惑的是,案例中的键MessageAWrapper 将是 @"value")。您的子类甚至不需要知道 C++ 代码。

您还可以将 -init+fromString: 方法中的 creator 函数分离为 +_createNewInstance;

+(Message*)_createNewInstance{ return new MessageA(); }

允许 MessageWrapper 的子类重用除创建 C++ 对象之外的所有代码。

关于objective-c - 有没有办法将 Protocol Buffer 包装到 Objective-C 中并仍然利用继承?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13369652/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com