2013-07-31 12 views
5

Utilizziamo i buffer di protocollo (2.4.1) in un sistema incorporato di medie dimensioni con codice C++ c /. Utilizziamo protobuf per isolare i nostri layer gestiti e nativi con uno strato di serializzazione facile da mantenere (per curiosità, avremmo appena usato Pinvoke, ma dobbiamo anche eseguire codice nativo in un processo separato su test/simulatori).- generatori di accessi NON in linea

Il nostro sistema ha un numero di DLL, e ho il codice nativo protobuf generato nella sua DLL in modo che le altre parti del sistema non possano collegare direttamente il codice generato.

Il problema sto avendo è che tutte le funzioni di accesso generate sono linea, ad esempio:

inline const ::MyProtoClassName::MyField& MyProtoClassName::myfield() const 
{ 
    return myfield_ != NULL ? *myfield_ : *default_instance_->myfield_; 
} 

utilizzare l'API generato dimensioni (il 'default_instance_' viene dereference e accessibile se questa particolare campo non impostato). Ciò significa che non posso collegare (lnk2001) nessun client usando gli accessor perché non c'è il simbolo default_instance_

Penso che il tipico caso d'uso per ProtoBufs sia quello di avere ogni collegamento di componente nel codice generato protobuf stesso (dopo tutto , questo è principalmente uno strato di serializzazione per sistemi distribuiti), ma

Mi chiedo se ci sia un interruttore di compilazione per modificare il comportamento di allineamento che ho perso. (Avere tutti gli accessors definiti nel file CC, non H)

Grazie!


  • Grazie @g-makulik! Sembra che la risposta è stata di circa 30 righe in codice ProtoC, ho appena fatto non vedo :)

    • < vedere la sua risposta qui sotto per la maggior parte della soluzione> Questo dovrebbe anche aiutare, però.

Come notato in alcuni dei changelog di Kenton, aggiungendo questo provoca vari avvertimenti (C4251, c4275) relative alle classi di base che non sono anche DLLEXPORT'd

con il modo in cui è implementato ProtoBufs, e le classi protobuf sono tutti modelli, questi avvertimenti sono benigni. Per ignorarli in modo pulito (ad esempio senza dover disabilitare gli avvisi per tutti i client) ho usato questo approccio un po 'hacky:

- wrapper per il file protobuf.h incluso in eveyone.(Nessuno includere il file H reale generato)

#pragma once 
    #pragma warning(push) 
    #pragma warning(disable:4251) 
    #pragma warning(disable:4275) 
    // include the protobuf generated code; but exclude the warn c4251, c4275 
    // these relate to the dll exported  
    #include "yourProtoFile.h" 
    #pragma warning(pop) 

e un file wrapper di C (il file CC vera protobuf non è nel mio progetto -> Non integrato direttamente)

#include "MyProtoFile_WRAPPER.h" 
#include "MyProtoFile.cc" 
+0

Vedo nel codice ProtoC che il codice funzione inline gen sembra essere chiamato solo dalla chiamata GenerateHeader (...) ... ma spero che Internet abbia risolto questo problema prima di me! :) – mike

risposta

4

penso questo link potrebbe rispondere alla tua domanda: Protobuf with MSVC: how to export generated Message

Citazione di Kenon Varga (Project leader di google protobuf):

Se richiamare ProtoC come:

ProtoC --cpp_out = dllexport_decl = MY_EXPORT_MACRO: path/to/uscita/dir myproto.proto

allora sarà generare il codice con MY_EXPORT_MACRO in tutti i posti giusti. Tuttavia, questa opzione è incompleta - attualmente non c'è modo di forzare il file .pb.h generato a #includere un'intestazione che definisce MY_EXPORT_MACRO. Sono aperto alle patch per risolvere questo problema. Oppure, potresti usare un trucco per aggirare il problema, ad esempio aggiungere #include tramite una sorta di elaborazione di testo dopo la chiusura di protoc, o forse spostare il file .pb.h in .pb2.h e sostituire il file .pb.h con uno che include prima l'intestazione include poi il .pb2.h ...

E Additonally per coprire l'incompletezza menzionato (Citazione di Aron Bierbaum):

al momento aggirare questa limitazione forzando l'intestazione su da includere utilizzando i flag della riga di comando del compilatore:

Windows:/FIproject/Con Fig.H
Linux: progetto -include/config.h

NOTA:
utilizzando la parola chiave inline non dovrebbe essere rilevante in questo caso (che un ulteriore attributo __declspec dllexport/__declspec dllimport è messo sul metodo di accesso). Per definizione spetta al compilatore alle funzioni inline o meno. Ovviamente vedere un attributo __declspec dllexport o __declspec dllimport è contraddittorio per l'inlining.

+0

@mike THX per l'accettazione. Basta chiacchierare un po 'sull'argomento ;-). Potresti dover aggiornare la tua domanda con la soluzione finale che hai trovato. Fornisce opzioni di formattazione migliori almeno ... –

+0

Per i miei commenti, vedere la mia "risposta" nella mia domanda, così posso formattarli in modo corretto. – mike

+0

@mike Sembra molto meglio! –