I'm messing around with Protobuf, trying to get C data over to C# which I then use to use the designated data within Unity. Seeing as Unity makes use of GameObjects like for example a sphere, having both positional data als scaling data, I figured I would try to use this format within the Protobuf message. This leads to the message looking somewhat like this:
syntax = "proto3";
package Sphere;
message Sphere {
message Position {
float x = 1;
float y = 2;
float z = 3;
}
message Scale {
float x = 1;
float y = 2;
float z = 3;
}
}
message Spheres {
repeated Sphere spheres = 1;
}
Now my question on this is how I can attach the Position and Scale values to a Sphere object within the C file.
As of right now my C file looks like this:
#include <fstream>
#include "sphere.pb.h"
using std::fstream;
Sphere::Sphere sphere1, sphere2;
Sphere::Spheres sphereCollection;
int main() {
using namespace Sphere;
std::fstream sphereData("./Assets/Scripts/sphereData.dat", std::ios::binary|std::ios::out);
Sphere_Position* position1;
position1->set_x(5);
position1->set_y(5);
position1->set_z(5);
Sphere_Scale* scale1;
scale1->set_x(5);
scale1->set_y(5);
scale1->set_z(5);
Sphere_Position* position2;
position2->set_x(5);
position2->set_y(5);
position2->set_z(5);
Sphere_Scale* scale2;
scale2->set_x(5);
scale2->set_y(5);
scale2->set_z(5);
sphereCollection.add_spheres()->CopyFrom(sphere1);
sphereCollection.add_spheres()->CopyFrom(sphere2);
sphereCollection.SerializeToOstream(&sphereData);
return EXIT_SUCCESS;
}
I figured that there should be some way I could maybe use the CopyFrom function to get the data from the Sphere_Position and Sphere_Scale, I however couldn't find a function that the CopyFrom function could be used on. I did relocate the Position and Scale messages to be contained within the Sphere message and recompiled the C generated classes afterwards, though I don't know if this was a change worth doing.
Please do note my C knowledge ain't all too bright as of yet, same could be said about Protobuf, though I have extensively checked Google's guide about it. (Ofcourse this does not exclude the possibility of me having missed something)
EDIT:
This is the sphere.pb.h:
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: sphere.proto
#ifndef PROTOBUF_INCLUDED_sphere_2eproto
#define PROTOBUF_INCLUDED_sphere_2eproto
#include <string>
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 3006001
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3006001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.
#endif
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_table_driven.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/inlined_string_field.h>
#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
#include <google/protobuf/extension_set.h> // IWYU pragma: export
#include <google/protobuf/unknown_field_set.h>
// @@protoc_insertion_point(includes)
#define PROTOBUF_INTERNAL_EXPORT_protobuf_sphere_2eproto
namespace protobuf_sphere_2eproto {
// Internal implementation detail -- do not use these members.
struct TableStruct {
static const ::google::protobuf::internal::ParseTableField entries[];
static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
static const ::google::protobuf::internal::ParseTable schema[4];
static const ::google::protobuf::internal::FieldMetadata field_metadata[];
static const ::google::protobuf::internal::SerializationTable serialization_table[];
static const ::google::protobuf::uint32 offsets[];
};
void AddDescriptors();
} // namespace protobuf_sphere_2eproto
namespace Sphere {
class Sphere;
class SphereDefaultTypeInternal;
extern SphereDefaultTypeInternal _Sphere_default_instance_;
class Sphere_Position;
class Sphere_PositionDefaultTypeInternal;
extern Sphere_PositionDefaultTypeInternal _Sphere_Position_default_instance_;
class Sphere_Scale;
class Sphere_ScaleDefaultTypeInternal;
extern Sphere_ScaleDefaultTypeInternal _Sphere_Scale_default_instance_;
class Spheres;
class SpheresDefaultTypeInternal;
extern SpheresDefaultTypeInternal _Spheres_default_instance_;
} // namespace Sphere
namespace google {
namespace protobuf {
template<> ::Sphere::Sphere* Arena::CreateMaybeMessage<::Sphere::Sphere>(Arena*);
template<> ::Sphere::Sphere_Position* Arena::CreateMaybeMessage<::Sphere::Sphere_Position>(Arena*);
template<> ::Sphere::Sphere_Scale* Arena::CreateMaybeMessage<::Sphere::Sphere_Scale>(Arena*);
template<> ::Sphere::Spheres* Arena::CreateMaybeMessage<::Sphere::Spheres>(Arena*);
} // namespace protobuf
} // namespace google
namespace Sphere {
// ===================================================================
class Sphere_Position : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Sphere.Sphere.Position) */ {
public:
Sphere_Position();
virtual ~Sphere_Position();
Sphere_Position(const Sphere_Position& from);
inline Sphere_Position& operator=(const Sphere_Position& from) {
CopyFrom(from);
return *this;
}
#if LANG_CXX11
Sphere_Position(Sphere_Position&& from) noexcept
: Sphere_Position() {
*this = ::std::move(from);
}
inline Sphere_Position& operator=(Sphere_Position&& from) noexcept {
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
if (this != &from) InternalSwap(&from);
} else {
CopyFrom(from);
}
return *this;
}
#endif
static const ::google::protobuf::Descriptor* descriptor();
static const Sphere_Position& default_instance();
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
static inline const Sphere_Position* internal_default_instance() {
return reinterpret_cast<const Sphere_Position*>(
&_Sphere_Position_default_instance_);
}
static constexpr int kIndexInFileMessages =
0;
void Swap(Sphere_Position* other);
friend void swap(Sphere_Position& a, Sphere_Position& b) {
a.Swap(&b);
}
// implements Message ----------------------------------------------
inline Sphere_Position* New() const final {
return CreateMaybeMessage<Sphere_Position>(NULL);
}
Sphere_Position* New(::google::protobuf::Arena* arena) const final {
return CreateMaybeMessage<Sphere_Position>(arena);
}
void CopyFrom(const ::google::protobuf::Message& from) final;
void MergeFrom(const ::google::protobuf::Message& from) final;
void CopyFrom(const Sphere_Position& from);
void MergeFrom(const Sphere_Position& from);
void Clear() final;
bool IsInitialized() const final;
size_t ByteSizeLong() const final;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) final;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const final;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* target) const final;
int GetCachedSize() const final { return _cached_size_.Get(); }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Sphere_Position* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return NULL;
}
inline void* MaybeArenaPtr() const {
return NULL;
}
public:
::google::protobuf::Metadata GetMetadata() const final;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// float x = 1;
void clear_x();
static const int kXFieldNumber = 1;
float x() const;
void set_x(float value);
// float y = 2;
void clear_y();
static const int kYFieldNumber = 2;
float y() const;
void set_y(float value);
// float z = 3;
void clear_z();
static const int kZFieldNumber = 3;
float z() const;
void set_z(float value);
// @@protoc_insertion_point(class_scope:Sphere.Sphere.Position)
private:
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
float x_;
float y_;
float z_;
mutable ::google::protobuf::internal::CachedSize _cached_size_;
friend struct ::protobuf_sphere_2eproto::TableStruct;
};
// -------------------------------------------------------------------
class Sphere_Scale : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Sphere.Sphere.Scale) */ {
public:
Sphere_Scale();
virtual ~Sphere_Scale();
Sphere_Scale(const Sphere_Scale& from);
inline Sphere_Scale& operator=(const Sphere_Scale& from) {
CopyFrom(from);
return *this;
}
#if LANG_CXX11
Sphere_Scale(Sphere_Scale&& from) noexcept
: Sphere_Scale() {
*this = ::std::move(from);
}
inline Sphere_Scale& operator=(Sphere_Scale&& from) noexcept {
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
if (this != &from) InternalSwap(&from);
} else {
CopyFrom(from);
}
return *this;
}
#endif
static const ::google::protobuf::Descriptor* descriptor();
static const Sphere_Scale& default_instance();
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
static inline const Sphere_Scale* internal_default_instance() {
return reinterpret_cast<const Sphere_Scale*>(
&_Sphere_Scale_default_instance_);
}
static constexpr int kIndexInFileMessages =
1;
void Swap(Sphere_Scale* other);
friend void swap(Sphere_Scale& a, Sphere_Scale& b) {
a.Swap(&b);
}
// implements Message ----------------------------------------------
inline Sphere_Scale* New() const final {
return CreateMaybeMessage<Sphere_Scale>(NULL);
}
Sphere_Scale* New(::google::protobuf::Arena* arena) const final {
return CreateMaybeMessage<Sphere_Scale>(arena);
}
void CopyFrom(const ::google::protobuf::Message& from) final;
void MergeFrom(const ::google::protobuf::Message& from) final;
void CopyFrom(const Sphere_Scale& from);
void MergeFrom(const Sphere_Scale& from);
void Clear() final;
bool IsInitialized() const final;
size_t ByteSizeLong() const final;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) final;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const final;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* target) const final;
int GetCachedSize() const final { return _cached_size_.Get(); }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Sphere_Scale* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return NULL;
}
inline void* MaybeArenaPtr() const {
return NULL;
}
public:
::google::protobuf::Metadata GetMetadata() const final;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// float x = 1;
void clear_x();
static const int kXFieldNumber = 1;
float x() const;
void set_x(float value);
// float y = 2;
void clear_y();
static const int kYFieldNumber = 2;
float y() const;
void set_y(float value);
// float z = 3;
void clear_z();
static const int kZFieldNumber = 3;
float z() const;
void set_z(float value);
// @@protoc_insertion_point(class_scope:Sphere.Sphere.Scale)
private:
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
float x_;
float y_;
float z_;
mutable ::google::protobuf::internal::CachedSize _cached_size_;
friend struct ::protobuf_sphere_2eproto::TableStruct;
};
// -------------------------------------------------------------------
class Sphere : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Sphere.Sphere) */ {
public:
Sphere();
virtual ~Sphere();
Sphere(const Sphere& from);
inline Sphere& operator=(const Sphere& from) {
CopyFrom(from);
return *this;
}
#if LANG_CXX11
Sphere(Sphere&& from) noexcept
: Sphere() {
*this = ::std::move(from);
}
inline Sphere& operator=(Sphere&& from) noexcept {
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
if (this != &from) InternalSwap(&from);
} else {
CopyFrom(from);
}
return *this;
}
#endif
static const ::google::protobuf::Descriptor* descriptor();
static const Sphere& default_instance();
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
static inline const Sphere* internal_default_instance() {
return reinterpret_cast<const Sphere*>(
&_Sphere_default_instance_);
}
static constexpr int kIndexInFileMessages =
2;
void Swap(Sphere* other);
friend void swap(Sphere& a, Sphere& b) {
a.Swap(&b);
}
// implements Message ----------------------------------------------
inline Sphere* New() const final {
return CreateMaybeMessage<Sphere>(NULL);
}
Sphere* New(::google::protobuf::Arena* arena) const final {
return CreateMaybeMessage<Sphere>(arena);
}
void CopyFrom(const ::google::protobuf::Message& from) final;
void MergeFrom(const ::google::protobuf::Message& from) final;
void CopyFrom(const Sphere& from);
void MergeFrom(const Sphere& from);
void Clear() final;
bool IsInitialized() const final;
size_t ByteSizeLong() const final;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) final;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const final;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* target) const final;
int GetCachedSize() const final { return _cached_size_.Get(); }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Sphere* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return NULL;
}
inline void* MaybeArenaPtr() const {
return NULL;
}
public:
::google::protobuf::Metadata GetMetadata() const final;
// nested types ----------------------------------------------------
typedef Sphere_Position Position;
typedef Sphere_Scale Scale;
// accessors -------------------------------------------------------
// @@protoc_insertion_point(class_scope:Sphere.Sphere)
private:
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
mutable ::google::protobuf::internal::CachedSize _cached_size_;
friend struct ::protobuf_sphere_2eproto::TableStruct;
};
// -------------------------------------------------------------------
class Spheres : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Sphere.Spheres) */ {
public:
Spheres();
virtual ~Spheres();
Spheres(const Spheres& from);
inline Spheres& operator=(const Spheres& from) {
CopyFrom(from);
return *this;
}
#if LANG_CXX11
Spheres(Spheres&& from) noexcept
: Spheres() {
*this = ::std::move(from);
}
inline Spheres& operator=(Spheres&& from) noexcept {
if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
if (this != &from) InternalSwap(&from);
} else {
CopyFrom(from);
}
return *this;
}
#endif
static const ::google::protobuf::Descriptor* descriptor();
static const Spheres& default_instance();
static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY
static inline const Spheres* internal_default_instance() {
return reinterpret_cast<const Spheres*>(
&_Spheres_default_instance_);
}
static constexpr int kIndexInFileMessages =
3;
void Swap(Spheres* other);
friend void swap(Spheres& a, Spheres& b) {
a.Swap(&b);
}
// implements Message ----------------------------------------------
inline Spheres* New() const final {
return CreateMaybeMessage<Spheres>(NULL);
}
Spheres* New(::google::protobuf::Arena* arena) const final {
return CreateMaybeMessage<Spheres>(arena);
}
void CopyFrom(const ::google::protobuf::Message& from) final;
void MergeFrom(const ::google::protobuf::Message& from) final;
void CopyFrom(const Spheres& from);
void MergeFrom(const Spheres& from);
void Clear() final;
bool IsInitialized() const final;
size_t ByteSizeLong() const final;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) final;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const final;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* target) const final;
int GetCachedSize() const final { return _cached_size_.Get(); }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const final;
void InternalSwap(Spheres* other);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return NULL;
}
inline void* MaybeArenaPtr() const {
return NULL;
}
public:
::google::protobuf::Metadata GetMetadata() const final;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// repeated .Sphere.Sphere spheres = 1;
int spheres_size() const;
void clear_spheres();
static const int kSpheresFieldNumber = 1;
::Sphere::Sphere* mutable_spheres(int index);
::google::protobuf::RepeatedPtrField< ::Sphere::Sphere >*
mutable_spheres();
const ::Sphere::Sphere& spheres(int index) const;
::Sphere::Sphere* add_spheres();
const ::google::protobuf::RepeatedPtrField< ::Sphere::Sphere >&
spheres() const;
// @@protoc_insertion_point(class_scope:Sphere.Spheres)
private:
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
::google::protobuf::RepeatedPtrField< ::Sphere::Sphere > spheres_;
mutable ::google::protobuf::internal::CachedSize _cached_size_;
friend struct ::protobuf_sphere_2eproto::TableStruct;
};
// ===================================================================
// ===================================================================
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif // __GNUC__
// Sphere_Position
// float x = 1;
inline void Sphere_Position::clear_x() {
x_ = 0;
}
inline float Sphere_Position::x() const {
// @@protoc_insertion_point(field_get:Sphere.Sphere.Position.x)
return x_;
}
inline void Sphere_Position::set_x(float value) {
x_ = value;
// @@protoc_insertion_point(field_set:Sphere.Sphere.Position.x)
}
// float y = 2;
inline void Sphere_Position::clear_y() {
y_ = 0;
}
inline float Sphere_Position::y() const {
// @@protoc_insertion_point(field_get:Sphere.Sphere.Position.y)
return y_;
}
inline void Sphere_Position::set_y(float value) {
y_ = value;
// @@protoc_insertion_point(field_set:Sphere.Sphere.Position.y)
}
// float z = 3;
inline void Sphere_Position::clear_z() {
z_ = 0;
}
inline float Sphere_Position::z() const {
// @@protoc_insertion_point(field_get:Sphere.Sphere.Position.z)
return z_;
}
inline void Sphere_Position::set_z(float value) {
z_ = value;
// @@protoc_insertion_point(field_set:Sphere.Sphere.Position.z)
}
// -------------------------------------------------------------------
// Sphere_Scale
// float x = 1;
inline void Sphere_Scale::clear_x() {
x_ = 0;
}
inline float Sphere_Scale::x() const {
// @@protoc_insertion_point(field_get:Sphere.Sphere.Scale.x)
return x_;
}
inline void Sphere_Scale::set_x(float value) {
x_ = value;
// @@protoc_insertion_point(field_set:Sphere.Sphere.Scale.x)
}
// float y = 2;
inline void Sphere_Scale::clear_y() {
y_ = 0;
}
inline float Sphere_Scale::y() const {
// @@protoc_insertion_point(field_get:Sphere.Sphere.Scale.y)
return y_;
}
inline void Sphere_Scale::set_y(float value) {
y_ = value;
// @@protoc_insertion_point(field_set:Sphere.Sphere.Scale.y)
}
// float z = 3;
inline void Sphere_Scale::clear_z() {
z_ = 0;
}
inline float Sphere_Scale::z() const {
// @@protoc_insertion_point(field_get:Sphere.Sphere.Scale.z)
return z_;
}
inline void Sphere_Scale::set_z(float value) {
z_ = value;
// @@protoc_insertion_point(field_set:Sphere.Sphere.Scale.z)
}
// -------------------------------------------------------------------
// Sphere
// -------------------------------------------------------------------
// Spheres
// repeated .Sphere.Sphere spheres = 1;
inline int Spheres::spheres_size() const {
return spheres_.size();
}
inline void Spheres::clear_spheres() {
spheres_.Clear();
}
inline ::Sphere::Sphere* Spheres::mutable_spheres(int index) {
// @@protoc_insertion_point(field_mutable:Sphere.Spheres.spheres)
return spheres_.Mutable(index);
}
inline ::google::protobuf::RepeatedPtrField< ::Sphere::Sphere >*
Spheres::mutable_spheres() {
// @@protoc_insertion_point(field_mutable_list:Sphere.Spheres.spheres)
return &spheres_;
}
inline const ::Sphere::Sphere& Spheres::spheres(int index) const {
// @@protoc_insertion_point(field_get:Sphere.Spheres.spheres)
return spheres_.Get(index);
}
inline ::Sphere::Sphere* Spheres::add_spheres() {
// @@protoc_insertion_point(field_add:Sphere.Spheres.spheres)
return spheres_.Add();
}
inline const ::google::protobuf::RepeatedPtrField< ::Sphere::Sphere >&
Spheres::spheres() const {
// @@protoc_insertion_point(field_list:Sphere.Spheres.spheres)
return spheres_;
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif // __GNUC__
// -------------------------------------------------------------------
// -------------------------------------------------------------------
// -------------------------------------------------------------------
// @@protoc_insertion_point(namespace_scope)
} // namespace Sphere
// @@protoc_insertion_point(global_scope)
#endif // PROTOBUF_INCLUDED_sphere_2eproto
CodePudding user response:
First, in addition to declaring your nested types, you also need to add fields to your message
message Sphere {
message Position {
float x = 1;
float y = 2;
float z = 3;
}
Position position = 1;
message Scale {
float x = 1;
float y = 2;
float z = 3;
}
Scale scale = 2;
}
then I would refactor how you create and populate the nested fields to something like
auto sphere1 = sphereCollection.add_spheres();
sphere1->mutable_position()->set_x(5);
sphere1->mutable_position()->set_y(5);
sphere1->mutable_position()->set_z(5);
sphere1->mutable_scale()->set_x(5);
sphere1->mutable_scale()->set_y(5);
sphere1->mutable_scale()->set_z(5);
auto sphere2 = sphereCollection.add_spheres();
sphere2->mutable_position()->set_x(5);
sphere2->mutable_position()->set_y(5);
sphere2->mutable_position()->set_z(5);
sphere2->mutable_scale()->set_x(5);
sphere2->mutable_scale()->set_y(5);
sphere2->mutable_scale()->set_z(5);
where you can use add_*
to allocate a nested repeated object from the current object and get a pointer back, and similarly mutable_*
for the desired field.