2015-05-08 13 views
16

Sto provando a creare una semplice applicazione di test con Protocol Buffers 2.6.1 e GNU GCC 5.1.0 (su Ubuntu 14.10) e ottengo seguenti errori:Riferimento indefinito a google :: protobuf :: internal :: empty_string_ [abi: cxx11]

/home/ragnar/cpp-tools/gcc-linux/bin/g++ -c "/home/ragnar/cpp-projects/gprotobuf_test/main.cpp" -g -O0 -Wall -o ./Debug/main.cpp.o -I. -I/home/ragnar/cpp-tools/libs/linux64/protobuf/include -I. 
/home/ragnar/cpp-tools/gcc-linux/bin/g++ -c "/home/ragnar/cpp-projects/gprotobuf_test/messages.pb.cc" -g -O0 -Wall -o ./Debug/messages.pb.cc.o -I. -I/home/ragnar/cpp-tools/libs/linux64/protobuf/include -I. 
/home/ragnar/cpp-tools/gcc-linux/bin/g++ -o ./Debug/gprotobuf_test @"gprotobuf_test.txt" -L. -L/home/ragnar/cpp-tools/libs/linux64/protobuf/lib -lprotobuf 
./Debug/main.cpp.o: In function google::protobuf::internal::GetEmptyStringAlreadyInited[abi:cxx11](): 
    /home/ragnar/cpp-tools/libs/linux64/protobuf/include/google/protobuf/generated_message_util.h:80: 
    undefined reference to google::protobuf::internal::empty_string_[abi:cxx11] 
    /home/ragnar/cpp-tools/libs/linux64/protobuf/include/google/protobuf/generated_message_util.h:81: 
    undefined reference to google::protobuf::internal::empty_string_[abi:cxx11] 
./Debug/messages.pb.cc.o: In function protobuf_AssignDesc_messages_2eproto(): 
    /home/ragnar/cpp-projects/gprotobuf_test/messages.pb.cc:32: 
    undefined reference to google::protobuf::DescriptorPool::FindFileByName(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const 
./Debug/messages.pb.cc.o: In function protobuf_AddDesc_messages_2eproto(): 
    /home/ragnar/cpp-projects/gprotobuf_test/messages.pb.cc:83: 
    undefined reference to google::protobuf::MessageFactory::InternalRegisterGeneratedFile(char const*, void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)) 
./Debug/messages.pb.cc.o: In function my_message::MergePartialFromCodedStream(google::protobuf::io::CodedInputStream*): 
    /home/ragnar/cpp-projects/gprotobuf_test/messages.pb.cc:187: 
    undefined reference to google::protobuf::internal::WireFormatLite::ReadString(google::protobuf::io::CodedInputStream*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) 
./Debug/messages.pb.cc.o: In function my_message::SerializeWithCachedSizes(google::protobuf::io::CodedOutputStream*) const: 
    /home/ragnar/cpp-projects/gprotobuf_test/messages.pb.cc:247: 
    undefined reference to google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, google::protobuf::io::CodedOutputStream*) 
./Debug/messages.pb.cc.o: In function google::protobuf::internal::WireFormatLite::WriteStringToArray(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned char*): 
    /home/ragnar/cpp-tools/libs/linux64/protobuf/include/google/protobuf/wire_format_lite_inl.h:749: 
    undefined reference to google::protobuf::io::CodedOutputStream::WriteStringWithSizeToArray(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned char*) 
./Debug/messages.pb.cc.o:(.rodata._ZTV10my_message[_ZTV10my_message]+0x20): 
    undefined reference to google::protobuf::Message::GetTypeName[abi:cxx11]() const 
./Debug/messages.pb.cc.o:(.rodata._ZTV10my_message[_ZTV10my_message]+0x40): 
    undefined reference to google::protobuf::Message::InitializationErrorString[abi:cxx11]() const 
collect2: error: ld returned 1 exit status 
gprotobuf_test.mk:93: recipe for target "Debug/gprotobuf_test" failed 
make[1]: *** [Debug/gprotobuf_test] Error 1 
make[1]: Leaving directory "/home/ragnar/cpp-projects/gprotobuf_test" 
Makefile:4: recipe for target "All" failed 
make: *** [All] Error 2 

il/home/Ragnar/CPP-tools/libs/linux64/protobuf/lib contiene seguenti librerie:

libprotobuf.a 
libprotobuf.so.9.0.1 
libprotobuf-lite.a 
libprotobuf-lite.so.9.0.1 
libprotoc.a 
libprotoc.so.9.0.1 

Ecco il semplice file messages.proto:

option java_package = "my.package"; 

message my_message { 
    required string word = 1; 
    required uint32 number = 2; 
} 

e il codice che sto cercando di far funzionare:

#include <iostream> 
#include <vector> 
#include <google/protobuf/io/coded_stream.h> 
#include <google/protobuf/io/zero_copy_stream_impl.h> 
#include "messages.pb.h" 

std::vector<unsigned char> encode(google::protobuf::Message & msg) 
{ 
    std::vector<unsigned char> data(msg.ByteSize() + 
    google::protobuf::io::CodedOutputStream::VarintSize32(msg.ByteSize())); 
    google::protobuf::io::ArrayOutputStream array_out(&data[0], data.size()); 
    google::protobuf::io::CodedOutputStream coded_out(&array_out); 
    coded_out.WriteVarint32(msg.ByteSize()); 
    msg.SerializeToCodedStream(&coded_out); 
    return data; 
} 

void decode(const std::vector<unsigned char> & data, google::protobuf::Message & msg) 
{ 
    google::protobuf::io::ArrayInputStream array_in(&data[0] , data.size()); 
    google::protobuf::io::CodedInputStream coded_in(&array_in); 
    google::protobuf::uint32 size; 
    coded_in.ReadVarint32(&size); 
    google::protobuf::io::CodedInputStream::Limit msg_limit = coded_in.PushLimit(size); 
    msg.ParseFromCodedStream(&coded_in); 
    coded_in.PopLimit(msg_limit); 
} 

int main(int argc, char **argv) 
{ 
    my_message in_msg; 
    in_msg.set_word(\"blah blah\"); 
    in_msg.set_number(123); 
    std::vector<unsigned char> data = encode(in_msg); 

    my_message out_msg; 
    decode(data, out_msg); 
    std::cout << \"word: \" << out_msg.word() << \" number: \" << out_msg.number() << std::endl; 
    return 0; 
} 

Gcc è costruito dalla sorgente con seguenti opzioni:

e Protobuf è costruito dalla sorgente con seguenti opzioni:

--enable-64it --disable-32bit --enable-shared CXXFLAGS=-m64 -DNDEBUG LDFLAGS=-m64 

Qualsiasi aiuto sarebbe molto apprezzato.

risposta

25

Sospetto che si tratti di un problema ABI C++. L'ABI per std::string è stato modificato in GCC 5 (relativo ai requisiti C++ 11, ma si applica anche se non si utilizza C++ 11). Vedere:

https://gcc.gnu.org/gcc-5/changes.html#libstdcxx

Se libprotobuf è stato costruito con 4.x GCC o prima, ma la vostra applicazione è costruito con GCC 5, poi si vedrà problemi, perché libprotobuf utilizza std::string nella sua interfaccia. Hai due opzioni:

  1. Ricostruisci libprotobuf con GCC 5 (ma ora tutte le app create con GCC 4 non funzioneranno con la nuova versione di libprotobuf).
  2. Crea l'app con -D_GLIBCXX_USE_CXX11_ABI=0 come descritto nel link precedente. Ciò imporrà a GCC di utilizzare la vecchia versione ABI.
+1

Ciao, puoi dire dove includere -D_GLIBCXX_USE_CXX11_ABI = 0. L'ho incluso nella cartella Makefile in caffe alla riga 245. Non sembra che abbia apportato alcuna modifica. Grazie. – awhitesong

5

ho avuto problema simile a

writeProto.cpp:(.text+0x2a8): undefined reference to `google::protobuf::internal::VerifyVersion(int, int, char const*)' 
writeProto.cpp:(.text+0x308): undefined reference to `tutorial::AddressBook::AddressBook()' 
writeProto.cpp:(.text+0x3a2): undefined reference to `google::protobuf::Message::ParseFromIstream(std::istream*)' 
writeProto.cpp:(.text+0x463): undefined reference to `google::protobuf::Message::SerializeToOstream(std::ostream*) const' 
writeProto.cpp:(.text+0x4b4): undefined reference to `google::protobuf::ShutdownProtobufLibrary()' 
writeProto.cpp:(.text+0x4c8): undefined reference to `tutorial::AddressBook::~AddressBook()' 
writeProto.cpp:(.text+0x515): undefined reference to `tutorial::AddressBook::~AddressBook()' 

Ho scritto questo sulla riga di comando e ora il mio codice funziona.

c++ writeProto.cpp addressbook.pb.cc `pkg-config --cflags --libs protobuf` 
+0

Questo ha risolto il problema, ma come? –

+2

@MaksimGayduk Per compilare un pacchetto che utilizza i buffer del protocollo, è necessario passare vari indicatori al compilatore e al linker. Protocol Buffers si integra con pkg-config per gestirlo. Se hai installato pkg-config, puoi richiamarlo per ottenere un elenco di flag. E poi scrivilo sulla riga di comando: C++ my_program.cc my_proto.pb.cc 'pkg-config --cflags --libs protobuf' –

+0

Questo è un problema separato dalla domanda originale .. ma sì pkg-config è normalmente il migliore pratica qui – moof2k