Google Protocol Buffers are an interesting example of an extensible format for serializing structured data in a portable and efficent manner suitable for streaming across the wire or into storage. The reference implementation accomplishes this in C++, but there are implementations for many other languages. In addition to one that generates pure perl code there also exists one that generates XS code on top of the natively generated C++ libraries.
Below you will find the XS and related components generated by protobuf-perlxs in the examples/simple demo from the distribution. They are presented here for the benefit of anyone lacking compilers, prerequisites, or time to mess with protobuf-perlxs themselves.
person.proto
Makefile.PL
Person.xs
person.pb.h
person.pb.cc
Enjoy,
Matt
person.proto
This is the actual protocol buffer specification, which the various protobuf implementations will compile into their particular idiom.
message Person {
required int32 id = 1;
required string name = 2;
optional string email = 3;
}
option optimize_for = SPEED;
Makefile.PL
use ExtUtils::MakeMaker;
$CC = 'g++';
# Generate the C++, XS, and Perl files that we need.
my $protoxs = "protoxs --cpp_out=. --out=. person.proto";
print "Generating C++ and Perl/XS sources...\n";
print "$protoxs\n";
`$protoxs`;
# Now write the Makefile.
WriteMakefile(
'NAME' => 'Person',
'VERSION_FROM' => 'Person.pm',
'OPTIMIZE' => '-O2 -Wall',
'CC' => $CC,
'LD' => '$(CC)',
'CCFLAGS' => '-fno-strict-aliasing',
'OBJECT' => 'person.pb.o Person.o',
'INC' => "",
'LIBS' => [" -lprotobuf"],
'XSOPT' => '-C++',
clean => { FILES => "Person.* person.pb.* lib" }
);
Person.xs
The generated XS code.
#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifdef __cplusplus
}
#endif
#ifdef do_open
#undef do_open
#endif
#ifdef do_close
#undef do_close
#endif
#ifdef New
#undef New
#endif
#include <stdint.h>
#include <sstream>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include "person.pb.h"
using namespace std;
class person_OutputStream :
public google::protobuf::io::ZeroCopyOutputStream {
public:
explicit person_OutputStream(SV * sv) :
sv_(sv), len_(0) {}
~person_OutputStream() {}
bool Next(void** data, int* size)
{
STRLEN nlen = len_ << 1;
if ( nlen < 16 ) nlen = 16;
SvGROW(sv_, nlen);
*data = SvEND(sv_) + len_;
*size = SvLEN(sv_) - len_;
len_ = nlen;
return true;
}
void BackUp(int count)
{
SvCUR_set(sv_, SvLEN(sv_) - count);
}
void Sync() {
if ( SvCUR(sv_) == 0 ) {
SvCUR_set(sv_, len_);
}
}
int64_t ByteCount() const
{
return (int64_t)SvCUR(sv_);
}
private:
SV * sv_;
STRLEN len_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(person_OutputStream);
};
typedef ::Person __Person;
static ::Person *
__Person_from_hashref ( SV * sv0 )
{
::Person * msg0 = new ::Person;
if ( SvROK(sv0) && SvTYPE(SvRV(sv0)) == SVt_PVHV ) {
HV * hv0 = (HV *)SvRV(sv0);
SV ** sv1;
if ( (sv1 = hv_fetch(hv0, "id", sizeof("id") - 1, 0)) != NULL ) {
msg0->set_id(SvIV(*sv1));
}
if ( (sv1 = hv_fetch(hv0, "name", sizeof("name") - 1, 0)) != NULL
+) {
STRLEN len;
char * str;
string sval;
str = SvPV(*sv1, len);
sval.assign(str, len);
msg0->set_name(sval);
}
if ( (sv1 = hv_fetch(hv0, "email", sizeof("email") - 1, 0)) != NUL
+L ) {
STRLEN len;
char * str;
string sval;
str = SvPV(*sv1, len);
sval.assign(str, len);
msg0->set_email(sval);
}
}
return msg0;
}
MODULE = Person PACKAGE = Person
PROTOTYPES: ENABLE
SV *
::Person::new (...)
PREINIT:
::Person * rv = NULL;
CODE:
if ( strcmp(CLASS,"Person") ) {
croak("invalid class %s",CLASS);
}
if ( items == 2 && ST(1) != Nullsv ) {
if ( SvROK(ST(1)) && SvTYPE(SvRV(ST(1))) == SVt_PVHV ) {
rv = __Person_from_hashref(ST(1));
} else {
STRLEN len;
char * str;
rv = new ::Person;
str = SvPV(ST(1), len);
if ( str != NULL ) {
rv->ParseFromArray(str, len);
}
}
} else {
rv = new ::Person;
}
RETVAL = newSV(0);
sv_setref_pv(RETVAL, "Person", (void *)rv);
OUTPUT:
RETVAL
void
DESTROY(svTHIS)
SV * svTHIS;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
delete THIS;
}
void
copy_from(svTHIS, sv)
SV * svTHIS
SV * sv
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL && sv != NULL ) {
if ( sv_derived_from(sv, "Person") ) {
IV tmp = SvIV((SV *)SvRV(sv));
::Person * other = INT2PTR(__Person *, tmp);
THIS->CopyFrom(*other);
} else if ( SvROK(sv) &&
SvTYPE(SvRV(sv)) == SVt_PVHV ) {
::Person * other = __Person_from_hashref(sv);
THIS->CopyFrom(*other);
delete other;
}
}
void
merge_from(svTHIS, sv)
SV * svTHIS
SV * sv
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL && sv != NULL ) {
if ( sv_derived_from(sv, "Person") ) {
IV tmp = SvIV((SV *)SvRV(sv));
::Person * other = INT2PTR(__Person *, tmp);
THIS->MergeFrom(*other);
} else if ( SvROK(sv) &&
SvTYPE(SvRV(sv)) == SVt_PVHV ) {
::Person * other = __Person_from_hashref(sv);
THIS->MergeFrom(*other);
delete other;
}
}
void
clear(svTHIS)
SV * svTHIS
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
THIS->Clear();
}
int
is_initialized(svTHIS)
SV * svTHIS
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
RETVAL = THIS->IsInitialized();
} else {
RETVAL = 0;
}
OUTPUT:
RETVAL
SV *
error_string(svTHIS)
SV * svTHIS
PREINIT:
string estr;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
estr = THIS->InitializationErrorString();
}
RETVAL = newSVpv(estr.c_str(), estr.length());
OUTPUT:
RETVAL
void
discard_unkown_fields(svTHIS)
SV * svTHIS
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
THIS->DiscardUnknownFields();
}
SV *
debug_string(svTHIS)
SV * svTHIS
PREINIT:
string dstr;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
dstr = THIS->DebugString();
}
RETVAL = newSVpv(dstr.c_str(), dstr.length());
OUTPUT:
RETVAL
SV *
short_debug_string(svTHIS)
SV * svTHIS
PREINIT:
string dstr;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
dstr = THIS->ShortDebugString();
}
RETVAL = newSVpv(dstr.c_str(), dstr.length());
OUTPUT:
RETVAL
int
unpack(svTHIS, arg)
SV * svTHIS
SV * arg
PREINIT:
STRLEN len;
char * str;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
str = SvPV(arg, len);
if ( str != NULL ) {
RETVAL = THIS->ParseFromArray(str, len);
} else {
RETVAL = 0;
}
} else {
RETVAL = 0;
}
OUTPUT:
RETVAL
SV *
pack(svTHIS)
SV * svTHIS
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
RETVAL = newSVpvn("", 0);
person_OutputStream os(RETVAL);
if ( THIS->IsInitialized() ) {
if ( THIS->SerializePartialToZeroCopyStream(&os)!= true ) {
SvREFCNT_dec(RETVAL);
RETVAL = Nullsv;
} else {
os.Sync();
}
} else {
croak("Can't serialize message of type 'Person' because it is
+missing required fields: %s",
THIS->InitializationErrorString().c_str());
}
} else {
RETVAL = Nullsv;
}
OUTPUT:
RETVAL
int
length(svTHIS)
SV * svTHIS
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
RETVAL = THIS->ByteSize();
} else {
RETVAL = 0;
}
OUTPUT:
RETVAL
void
fields(svTHIS)
SV * svTHIS
PPCODE:
(void)svTHIS;
EXTEND(SP, 3);
PUSHs(sv_2mortal(newSVpv("id",0)));
PUSHs(sv_2mortal(newSVpv("name",0)));
PUSHs(sv_2mortal(newSVpv("email",0)));
SV *
to_hashref(svTHIS)
SV * svTHIS
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
HV * hv0 = newHV();
::Person * msg0 = THIS;
if ( msg0->has_id() ) {
SV * sv0 = newSViv(msg0->id());
hv_store(hv0, "id", sizeof("id") - 1, sv0, 0);
}
if ( msg0->has_name() ) {
SV * sv0 = newSVpv(msg0->name().c_str(), msg0->name().length()
+);
hv_store(hv0, "name", sizeof("name") - 1, sv0, 0);
}
if ( msg0->has_email() ) {
SV * sv0 = newSVpv(msg0->email().c_str(), msg0->email().length
+());
hv_store(hv0, "email", sizeof("email") - 1, sv0, 0);
}
RETVAL = newRV_noinc((SV *)hv0);
} else {
RETVAL = Nullsv;
}
OUTPUT:
RETVAL
I32
has_id(svTHIS)
SV * svTHIS;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
RETVAL = THIS->has_id();
OUTPUT:
RETVAL
void
clear_id(svTHIS)
SV * svTHIS;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
THIS->clear_id();
void
id(svTHIS)
SV * svTHIS;
PREINIT:
SV * sv;
PPCODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
EXTEND(SP,1);
sv = sv_2mortal(newSViv(THIS->id()));
PUSHs(sv);
}
void
set_id(svTHIS, svVAL)
SV * svTHIS
IV svVAL
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
THIS->set_id(svVAL);
I32
has_name(svTHIS)
SV * svTHIS;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
RETVAL = THIS->has_name();
OUTPUT:
RETVAL
void
clear_name(svTHIS)
SV * svTHIS;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
THIS->clear_name();
void
name(svTHIS)
SV * svTHIS;
PREINIT:
SV * sv;
PPCODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
EXTEND(SP,1);
sv = sv_2mortal(newSVpv(THIS->name().c_str(),
THIS->name().length()));
PUSHs(sv);
}
void
set_name(svTHIS, svVAL)
SV * svTHIS
SV *svVAL
PREINIT:
char * str;
STRLEN len;
string sval;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
str = SvPV(svVAL, len);
sval.assign(str, len);
THIS->set_name(sval);
I32
has_email(svTHIS)
SV * svTHIS;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
RETVAL = THIS->has_email();
OUTPUT:
RETVAL
void
clear_email(svTHIS)
SV * svTHIS;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
THIS->clear_email();
void
email(svTHIS)
SV * svTHIS;
PREINIT:
SV * sv;
PPCODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
if ( THIS != NULL ) {
EXTEND(SP,1);
sv = sv_2mortal(newSVpv(THIS->email().c_str(),
THIS->email().length()));
PUSHs(sv);
}
void
set_email(svTHIS, svVAL)
SV * svTHIS
SV *svVAL
PREINIT:
char * str;
STRLEN len;
string sval;
CODE:
::Person * THIS;
if ( sv_derived_from(svTHIS, "Person") ) {
IV tmp = SvIV((SV *)SvRV(svTHIS));
THIS = INT2PTR(__Person *, tmp);
} else {
croak("THIS is not of type Person");
}
str = SvPV(svVAL, len);
sval.assign(str, len);
THIS->set_email(sval);
person.pb.h
// Generated by the protocol buffer compiler. DO NOT EDIT!
#ifndef PROTOBUF_person_2eproto__INCLUDED
#define PROTOBUF_person_2eproto__INCLUDED
#include <string>
#include <google/protobuf/stubs/common.h>
#if GOOGLE_PROTOBUF_VERSION < 2002000
#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 2002000 < 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/generated_message_util.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/generated_message_reflection.h>
// Internal implementation detail -- do not call these.
void protobuf_AddDesc_person_2eproto();
void protobuf_AssignDesc_person_2eproto();
void protobuf_ShutdownFile_person_2eproto();
class Person;
// ===================================================================
class Person : public ::google::protobuf::Message {
public:
Person();
virtual ~Person();
Person(const Person& from);
inline Person& operator=(const Person& from) {
CopyFrom(from);
return *this;
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() c
+onst {
return _unknown_fields_;
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields()
+ {
return &_unknown_fields_;
}
static const ::google::protobuf::Descriptor* descriptor();
static const Person& default_instance();
void Swap(Person* other);
// implements Message ----------------------------------------------
Person* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const Person& from);
void MergeFrom(const Person& from);
void Clear();
bool IsInitialized() const;
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google:
+:protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// required int32 id = 1;
inline bool has_id() const;
inline void clear_id();
static const int kIdFieldNumber = 1;
inline ::google::protobuf::int32 id() const;
inline void set_id(::google::protobuf::int32 value);
// required string name = 2;
inline bool has_name() const;
inline void clear_name();
static const int kNameFieldNumber = 2;
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
// optional string email = 3;
inline bool has_email() const;
inline void clear_email();
static const int kEmailFieldNumber = 3;
inline const ::std::string& email() const;
inline void set_email(const ::std::string& value);
inline void set_email(const char* value);
inline void set_email(const char* value, size_t size);
inline ::std::string* mutable_email();
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::google::protobuf::int32 id_;
::std::string* name_;
static const ::std::string _default_name_;
::std::string* email_;
static const ::std::string _default_email_;
friend void protobuf_AddDesc_person_2eproto();
friend void protobuf_AssignDesc_person_2eproto();
friend void protobuf_ShutdownFile_person_2eproto();
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
inline bool _has_bit(int index) const {
return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
}
inline void _set_bit(int index) {
_has_bits_[index / 32] |= (1u << (index % 32));
}
inline void _clear_bit(int index) {
_has_bits_[index / 32] &= ~(1u << (index % 32));
}
void InitAsDefaultInstance();
static Person* default_instance_;
};
// ===================================================================
// ===================================================================
// ===================================================================
// Person
// required int32 id = 1;
inline bool Person::has_id() const {
return _has_bit(0);
}
inline void Person::clear_id() {
id_ = 0;
_clear_bit(0);
}
inline ::google::protobuf::int32 Person::id() const {
return id_;
}
inline void Person::set_id(::google::protobuf::int32 value) {
_set_bit(0);
id_ = value;
}
// required string name = 2;
inline bool Person::has_name() const {
return _has_bit(1);
}
inline void Person::clear_name() {
if (name_ != &_default_name_) {
name_->clear();
}
_clear_bit(1);
}
inline const ::std::string& Person::name() const {
return *name_;
}
inline void Person::set_name(const ::std::string& value) {
_set_bit(1);
if (name_ == &_default_name_) {
name_ = new ::std::string;
}
name_->assign(value);
}
inline void Person::set_name(const char* value) {
_set_bit(1);
if (name_ == &_default_name_) {
name_ = new ::std::string;
}
name_->assign(value);
}
inline void Person::set_name(const char* value, size_t size) {
_set_bit(1);
if (name_ == &_default_name_) {
name_ = new ::std::string;
}
name_->assign(reinterpret_cast<const char*>(value), size);
}
inline ::std::string* Person::mutable_name() {
_set_bit(1);
if (name_ == &_default_name_) {
name_ = new ::std::string;
}
return name_;
}
// optional string email = 3;
inline bool Person::has_email() const {
return _has_bit(2);
}
inline void Person::clear_email() {
if (email_ != &_default_email_) {
email_->clear();
}
_clear_bit(2);
}
inline const ::std::string& Person::email() const {
return *email_;
}
inline void Person::set_email(const ::std::string& value) {
_set_bit(2);
if (email_ == &_default_email_) {
email_ = new ::std::string;
}
email_->assign(value);
}
inline void Person::set_email(const char* value) {
_set_bit(2);
if (email_ == &_default_email_) {
email_ = new ::std::string;
}
email_->assign(value);
}
inline void Person::set_email(const char* value, size_t size) {
_set_bit(2);
if (email_ == &_default_email_) {
email_ = new ::std::string;
}
email_->assign(reinterpret_cast<const char*>(value), size);
}
inline ::std::string* Person::mutable_email() {
_set_bit(2);
if (email_ == &_default_email_) {
email_ = new ::std::string;
}
return email_;
}
#ifndef SWIG
namespace google {
namespace protobuf {
} // namespace google
} // namespace protobuf
#endif // SWIG
#endif // PROTOBUF_person_2eproto__INCLUDED
person.pb.cc
// Generated by the protocol buffer compiler. DO NOT EDIT!
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
#include "person.pb.h"
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
namespace {
const ::google::protobuf::Descriptor* Person_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
Person_reflection_ = NULL;
} // namespace
void protobuf_AssignDesc_person_2eproto() {
protobuf_AddDesc_person_2eproto();
const ::google::protobuf::FileDescriptor* file =
::google::protobuf::DescriptorPool::generated_pool()->FindFileByNa
+me(
"person.proto");
GOOGLE_CHECK(file != NULL);
Person_descriptor_ = file->message_type(0);
static const int Person_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Person, id_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Person, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Person, email_),
};
Person_reflection_ =
new ::google::protobuf::internal::GeneratedMessageReflection(
Person_descriptor_,
Person::default_instance_,
Person_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Person, _has_bits
+_[0]),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Person, _unknown_
+fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
sizeof(Person));
}
namespace {
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
inline void protobuf_AssignDescriptorsOnce() {
::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_
+,
&protobuf_AssignDesc_person_2eproto);
}
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage
+(
Person_descriptor_, &Person::default_instance());
}
} // namespace
void protobuf_ShutdownFile_person_2eproto() {
delete Person::default_instance_;
delete Person_reflection_;
}
void protobuf_AddDesc_person_2eproto() {
static bool already_here = false;
if (already_here) return;
already_here = true;
GOOGLE_PROTOBUF_VERIFY_VERSION;
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\014person.proto\"1\n\006Person\022\n\n\002id\030\001 \002(\005
+\022\014\n\004"
"name\030\002 \002(\t\022\r\n\005email\030\003 \001(\tB\002H\001",
+ 69);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"person.proto", &protobuf_RegisterTypes);
Person::default_instance_ = new Person();
Person::default_instance_->InitAsDefaultInstance();
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_pers
+on_2eproto);
}
// Force AddDescriptors() to be called at static initialization time.
struct StaticDescriptorInitializer_person_2eproto {
StaticDescriptorInitializer_person_2eproto() {
protobuf_AddDesc_person_2eproto();
}
} static_descriptor_initializer_person_2eproto_;
// ===================================================================
const ::std::string Person::_default_name_;
const ::std::string Person::_default_email_;
#ifndef _MSC_VER
const int Person::kIdFieldNumber;
const int Person::kNameFieldNumber;
const int Person::kEmailFieldNumber;
#endif // !_MSC_VER
Person::Person() {
SharedCtor();
}
void Person::InitAsDefaultInstance() {
}
Person::Person(const Person& from) {
SharedCtor();
MergeFrom(from);
}
void Person::SharedCtor() {
_cached_size_ = 0;
id_ = 0;
name_ = const_cast< ::std::string*>(&_default_name_);
email_ = const_cast< ::std::string*>(&_default_email_);
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
Person::~Person() {
SharedDtor();
}
void Person::SharedDtor() {
if (name_ != &_default_name_) {
delete name_;
}
if (email_ != &_default_email_) {
delete email_;
}
if (this != default_instance_) {
}
}
const ::google::protobuf::Descriptor* Person::descriptor() {
protobuf_AssignDescriptorsOnce();
return Person_descriptor_;
}
const Person& Person::default_instance() {
if (default_instance_ == NULL) protobuf_AddDesc_person_2eproto(); r
+eturn *default_instance_;
}
Person* Person::default_instance_ = NULL;
Person* Person::New() const {
return new Person;
}
void Person::Clear() {
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
id_ = 0;
if (_has_bit(1)) {
if (name_ != &_default_name_) {
name_->clear();
}
}
if (_has_bit(2)) {
if (email_ != &_default_email_) {
email_->clear();
}
}
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
mutable_unknown_fields()->Clear();
}
bool Person::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
::google::protobuf::uint32 tag;
while ((tag = input->ReadTag()) != 0) {
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldN
+umber(tag)) {
// required int32 id = 1;
case 1: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireTy
+pe(tag) !=
::google::protobuf::internal::WireFormatLite::WIRETYPE_VAR
+INT) {
goto handle_uninterpreted;
}
DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
input, &id_));
_set_bit(0);
if (input->ExpectTag(18)) goto parse_name;
break;
}
// required string name = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireTy
+pe(tag) !=
::google::protobuf::internal::WireFormatLite::WIRETYPE_LEN
+GTH_DELIMITED) {
goto handle_uninterpreted;
}
parse_name:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_name()));
::google::protobuf::internal::WireFormat::VerifyUTF8String(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectTag(26)) goto parse_email;
break;
}
// optional string email = 3;
case 3: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireTy
+pe(tag) !=
::google::protobuf::internal::WireFormatLite::WIRETYPE_LEN
+GTH_DELIMITED) {
goto handle_uninterpreted;
}
parse_email:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_email()));
::google::protobuf::internal::WireFormat::VerifyUTF8String(
this->email().data(), this->email().length(),
::google::protobuf::internal::WireFormat::PARSE);
if (input->ExpectAtEnd()) return true;
break;
}
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireTy
+pe(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END
+_GROUP) {
return true;
}
DO_(::google::protobuf::internal::WireFormat::SkipField(
input, tag, mutable_unknown_fields()));
break;
}
}
}
return true;
#undef DO_
}
void Person::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNB
+ytesAndAdvance(_cached_size_);
if (raw_buffer != NULL) {
Person::SerializeWithCachedSizesToArray(raw_buffer);
return;
}
// required int32 id = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->
+id(), output);
}
// required string name = 2;
if (_has_bit(1)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE);
::google::protobuf::internal::WireFormatLite::WriteString(
2, this->name(), output);
}
// optional string email = 3;
if (_has_bit(2)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
this->email().data(), this->email().length(),
::google::protobuf::internal::WireFormat::SERIALIZE);
::google::protobuf::internal::WireFormatLite::WriteString(
3, this->email(), output);
}
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
}
::google::protobuf::uint8* Person::SerializeWithCachedSizesToArray(
::google::protobuf::uint8* target) const {
// required int32 id = 1;
if (_has_bit(0)) {
target = ::google::protobuf::internal::WireFormatLite::WriteInt32T
+oArray(1, this->id(), target);
}
// required string name = 2;
if (_has_bit(1)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE);
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray
+(
2, this->name(), target);
}
// optional string email = 3;
if (_has_bit(2)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
this->email().data(), this->email().length(),
::google::protobuf::internal::WireFormat::SERIALIZE);
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray
+(
3, this->email(), target);
}
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknow
+nFieldsToArray(
unknown_fields(), target);
}
return target;
}
int Person::ByteSize() const {
int total_size = 0;
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// required int32 id = 1;
if (has_id()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::Int32Size(
this->id());
}
// required string name = 2;
if (has_name()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->name());
}
// optional string email = 3;
if (has_email()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->email());
}
}
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSi
+ze(
unknown_fields());
}
_cached_size_ = total_size;
return total_size;
}
void Person::MergeFrom(const ::google::protobuf::Message& from) {
GOOGLE_CHECK_NE(&from, this);
const Person* source =
::google::protobuf::internal::dynamic_cast_if_available<const Pers
+on*>(
&from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
MergeFrom(*source);
}
}
void Person::MergeFrom(const Person& from) {
GOOGLE_CHECK_NE(&from, this);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from._has_bit(0)) {
set_id(from.id());
}
if (from._has_bit(1)) {
set_name(from.name());
}
if (from._has_bit(2)) {
set_email(from.email());
}
}
mutable_unknown_fields()->MergeFrom(from.unknown_fields());
}
void Person::CopyFrom(const ::google::protobuf::Message& from) {
if (&from == this) return;
Clear();
MergeFrom(from);
}
void Person::CopyFrom(const Person& from) {
if (&from == this) return;
Clear();
MergeFrom(from);
}
bool Person::IsInitialized() const {
if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
return true;
}
void Person::Swap(Person* other) {
if (other != this) {
std::swap(id_, other->id_);
std::swap(name_, other->name_);
std::swap(email_, other->email_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.Swap(&other->_unknown_fields_);
std::swap(_cached_size_, other->_cached_size_);
}
}
::google::protobuf::Metadata Person::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
::google::protobuf::Metadata metadata;
metadata.descriptor = Person_descriptor_;
metadata.reflection = Person_reflection_;
return metadata;
}
Re: Protocol Buffers and XS
by BenGoldberg (Sexton) on Dec 28, 2013 at 01:40 UTC
|
If you are using Protocol Buffers for cross-language compatibility, it's quite possible that the classes declared in the foo.proto file (person.proto in your example) will clash with the name of some unrelated perl class.
For example, if someone wrote a Person class, put it on CPAN, and I wanted to use both that Person from CPAN and the example Person class generated by protoxs... I would have a problem.
It would be very useful to future users of this program if there were an option to allow all of the generated perl modules to have some sort of user-specified prefix.
| [reply] |
|
|