Буферы протокола Google для iOS
Является метасинтактической статической библиотекой для iOS.,
http://code.google.com/p/metasyntactic/wiki/ProtocolBuffers
., совместим с обычными старыми С++ скомпилированными прототипами? Я не хочу использовать составной компилятор, который генерирует Obj-C.
Есть ли способ скомпилировать библиотеку, предоставленную Google для iOS?
Ответы
Ответ 1
Ok. Похоже, что метасинтаксическая библиотека (или любая другая сторонняя библиотека) в этом случае не нужна. Вы можете просто добавить источник Google непосредственно в свой проект. Я нашел следующий ответ от Никола Ферруцци в группе обсуждения google.,.
Оригинальный ответ здесь.,
http://groups.google.com/group/protobuf/browse_thread/thread/ca4218d7db144252
Содержание этого ответа приведено ниже с изображениями, чтобы сделать постоянную запись...
ИЗМЕНИТЬ
С тех пор, как мы попробовали это снова сегодня вечером, мне понадобилось еще несколько шагов в дополнение к приведенным ниже (это работает с protobuf 2.5.0).
- Вам нужно будет установить ссылку на libz.dylib. Вы устанавливаете это в "Фазы сборки" > "Связывание двоичных файлов с библиотеками".
- Чтобы легко удалить все связанные с unit test вещи, используйте следующую команду из оболочки в каталоге google
find . -name "*unittest*" -exec rm -rf {} \;
- Также удалите папку с именем
testing
- комментарий
#include <google/protobuf/testing/googletest.h>
в stringprintf.cc
- Теперь внимательно следуйте приведенным ниже инструкциям, и все должно работать нормально.
Я использую последнюю версию в своем приложении.. вам действительно не нужно objc direct если вы знакомы с С++, есть только одна точка, где вам нужно перейти от std::string к NSData и наоборот. И это довольно простой.
Чтобы скомпилировать и протестировать самый простой способ, который я обнаружил, это просто импортировать весь каталог google в моем собственном проекте:) (во второй раз вы можете создайте свою собственную структуру, но для тестирования эта процедура просто работает)
- скачать последнюю версию
- autogen настроить и сделать так, как будто вы просто строили для macosx (вам нужны инструменты командной строки). Таким образом, вы в конечном итоге с протоком
двоичный и библиотека для macosx (что вам не нужно) - откройте проект iOS Xcode.
- добавьте "новый файл" в свой проект и выберите каталог google
- добавить каталог заголовков google в ваши дополнительные каталоги include
- добавить config.h из каталога protobuffer src в ваше приложение.
- из группы google удаляет все, что содержит unitest:)
- из группы google удалить компилятор и java файл;
Вы должны иметь возможность компилировать без какой-либо ошибки связывания. Чтобы дать вам идея заключается в том, что я непосредственно компилирую
![enter image description here]()
Затем вы можете использовать protoc для генерации исходных файлов С++ для вашего протокол. Чтобы использовать их с objc, вам нужно переименовать свой источник в file "mm", тогда вы можете сделать что-то вроде
ДЛЯ СЕРИАЛИЗАЦИИ NSDATA
скажем, ваше сообщение называется Packet
- (NSData *)getDataForPacket:(Packet *)packet {
std::string ps = packet->SerializeAsString();
return [NSData dataWithBytes:ps.c_str() length:ps.size()];
ЧИТАТЬ ИЗ NSDATA
- (Packet *)getPacketFromNSData:(NSData *)data {
char raw[[data length]];
Packet *p = new Packet;
[data getBytes:raw length:[data length]];
p->ParseFromArray(raw, [data length]);
return p;
}
Ответ 2
Вы можете добавить поддержку буферов протокола Google в проект Xcode 5 с использованием Cocoapods, добавив следующую строку в ваш подфайл.
pod 'GoogleProtobuf', '~> 2.5.0'
Это поместит версию протобуфа С++ в Pod для вашего проекта. Он также добавит компилятор protoc
в папку Pods/GoogleProtobuf/bin/protoc
в вашем проекте.
В проекте можно создать правило пользовательской сборки, которое автоматически преобразует файлы .proto
в файлы .ph.{h,cc}
. Вот как я это сделал:
Установите правило сборки для "Обработать исходные файлы с именами, соответствующими: *.proto Использование Custom Script". script должен включать следующее:
cd ${INPUT_FILE_DIR}
${SRCROOT}/Pods/GoogleProtobuf/bin/protoc --proto_path=${INPUT_FILE_DIR} ${INPUT_FILE_PATH} --cpp_out=${INPUT_FILE_DIR}/cpp
Задайте выходные файлы следующим образом:
$(INPUT_FILE_DIR)/cpp/$(INPUT_FILE_BASE).pb.h
$(INPUT_FILE_DIR)/cpp/$(INPUT_FILE_BASE).pb.cc
Любые .proto
файлы, которые вы включаете в свой проект, теперь будут автоматически преобразованы в С++ и затем скомпилированы как часть вашей сборки.
Ответ 3
РЕДАКТИРОВАТЬ: я ответил ранее, но был удален модератором. Поэтому я включил некоторый код из учебника.
Учебник, который почти такой же, как и выше, - Использование буферов протокола Google в Objective-C на iOS и Mac
Следуйте инструкциям, приведенным в ответе learnvst, и отсылайте комментарии к ошибкам. Я выполнил те же самые шаги, кроме
добавить каталог заголовков google в ваши дополнительные каталоги include Я добавил каталог src/ в пути поиска заголовков, а не в каталог google.
Кроме того, когда я сделал #import xyz.pb.h
, проект не строился. Когда я переименовал свой файл .m в .mm, я смог создать. Этот момент упоминается в учебнике очень тонко: P.
В принципе, любой файл .m, который импортирует любой файл .pb.h, должен быть переименован с расширением .mm
Вот некоторый контент из учебника -
ФАЙЛ ПРОТОКА
package kotancode;
enum ZombieType {
SLOW = 0;
FAST = 1;
}
message ZombieSighting {
required string name = 1;
required double longitude = 2;
required double latitude = 3;
optional string description = 4;
required ZombieType zombieType = 5 [default = SLOW];
}
ZombieSightingMessage.h
// -- ZombieSightingMessage.h - note my C++ object is not in the public interface.
#import <Foundation/Foundation.h>
@interface ZombieSightingMessage : NSObject
- (void)doSomething;
@end
ZombieSightingMessage.mm
// -- ZombieSightingMessage.mm
#import <UIKit/UIKit.h>
#import "ZombieSightingMessage.h"
#import "zombie.pb.h"
@implementation ZombieSightingMessage
- (void)doSomething {
// Doing random stuff with a UIView here to show the mixing
// of C++ and Objective-C/Cocoa syntax in the same file...
UIView *uiView = [[UIView alloc] init];
[uiView setCenter:CGPointMake(20, 10)];
// instantiate my protobuf-generated C++ class.
kotancode::ZombieSighting *zombieSighting = new kotancode::ZombieSighting();
zombieSighting->set_name("Kevin");
zombieSighting->set_description("This is a zombie");
zombieSighting->set_latitude(41.007);
zombieSighting->set_longitude(21.007);
zombieSighting->set_zombietype(kotancode::ZombieType::FAST);
// Some small tomfoolery required to go from C++ std::string to NSString.
std::string x = zombieSighting->DebugString();
NSString *output = [NSString stringWithCString:x.c_str() encoding:[NSString defaultCStringEncoding]];
NSLog(@"zombie: %@", output);
// Instantiate another zombie from the previous zombie raw bytes.
NSData *rawZombie = [self getDataForZombie:zombieSighting];
kotancode::ZombieSighting *otherZombie = [self getZombieFromData:rawZombie];
// Dump the second zombie so we can see they match identically...
NSString *newOutput = [NSString stringWithCString:otherZombie->DebugString().c_str() encoding:[NSString defaultCStringEncoding]];
NSLog(@"other zombie: %@", newOutput);
// Grimace all you want, but this is C++ and we need to clean up after ourselves.
free(zombieSighting);
free(otherZombie);
}
// Serialize to NSData. Note this is convenient because
// we can write NSData to things like sockets...
- (NSData *)getDataForZombie:(kotancode::ZombieSighting *)zombie {
std::string ps = zombie->SerializeAsString();
return [NSData dataWithBytes:ps.c_str() length:ps.size()];
}
// De-serialize a zombie from an NSData object.
- (kotancode::ZombieSighting *)getZombieFromData:(NSData *)data {
int len = [data length];
char raw[len];
kotancode::ZombieSighting *zombie = new kotancode::ZombieSighting;
[data getBytes:raw length:len];
zombie->ParseFromArray(raw, len);
return zombie;
}
@end
EDIT: я использую Xcode 4.5. Даже после того, как я выполнил все шаги, я получил ошибку компоновщика.
символы, не найденные для архитектуры i386
Из-за этого я не смог запустить код на симуляторе. Но он работал на самом устройстве
Ответ 4
Я предполагаю, что на основе фактического вопроса мой комментарий стоит опубликовать в качестве ответа:
Я использую слегка измененную версию генерации кода Obj, предоставленную Booyah
Он поддерживает повторяющиеся поля из коробки, но для использования быстрого перечисления ObjC вам необходимо преобразовать тип PBArray (в основном типизированный c-буфер) в массив NSObjects, который он представляет, либо сообщение NSNumber или protobuf объекты. Вы можете увидеть пример обновленного кода быстрого перечисления в это изменение:. Вы также можете добавить категорию для PBArray, вызываемой toObjects.
Я просто отмечаю сгенерированный код -fno-objc-arc
, но вы можете получить поддержку дуги и 2.5 из запросов booyah pull.
Направления очень хороши для настройки, но если людям нужны более явные инструкции по используемой категории, как я создал плагин protobuf-objc, как получить поддержку префиксов класса (например, IXMyProtoMessage вместо MyProtoMessage) или как я генерировать код, дайте мне знать, и я постараюсь выделить время, чтобы написать сообщение. Я использую его s > 50 прото файлами с большим количеством зависимостей между проектами.
Слабость библиотеки заключается в том, что она не включает типичное отражение APP Protobuf в сгенерированном коде, поэтому выполнение чего-то вроде преобразования сообщения в NSDictionary должно было бы сделать некоторые хакерские вещи в среде выполнения objC (код doesn ' t следуйте типичным требованиям KV) или напишите генератор пользовательского кода из протос, у которого есть отражение api (я сделал это с python + jinja2). Или - еще лучше и с подобной сложностью, добавьте отражение apis в генератор кода;).