6

私たちは、c# と c++ コードを使用する中規模の組み込みシステムでプロトコル バッファー (2.4.1) を使用しています。protobufs を使用して、マネージド レイヤーとネイティブ レイヤーを分離し、シリアル化レイヤーを簡単に維持できます (興味深いことに、Pinvoke を使用しただけですが、テスト/シミュレーターの別のプロセスでネイティブ コードを実行する必要もあります)。

私たちのシステムには多数の DLL があり、システムの他の部分が生成されたコードに直接リンクする必要がないように、独自の DLL に生成されたネイティブ protobuf コードがあります。

私が抱えている問題は、生成されたすべてのアクセサーがinlineであることです。

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

生成された API をサイズで使用します (この特定のフィールドが設定されていない場合、' default_instance_ ' は逆参照され、アクセスされます)。これは、シンボル default_instance_ がないため、アクセサーを使用しているクライアントをリンク (lnk2001) できないことを意味します。

ProtoBufs の典型的な使用例は、生成された protobuf コード自体に各コンポーネント リンクを含めることだと思います (結局のところ、これは主に分散システムのシリアライゼーション レイヤーです)。

私が見逃したインライン化の動作を変更するためのコンパイル スイッチがあるかどうか疑問に思っています。(H ではなく、CC ファイルですべてのアクセサを定義します)

ありがとう!


  • ありがとう@g-makulik!答えはProtoCコードの約30行だったようですが、私はそれを見ませんでした:)

    • <解決策の大部分については、以下の彼の回答を参照してください>ただし、これも役立つはずです。

Kenton の変更ログの一部で指摘されているように、これを追加すると、DLLEXPORT されていない基本クラスに関連するいくつかの警告 (C4251、c4275) が発生します。

ProtoBufs の実装方法と protobuf クラスがすべてテンプレートであるため、これらの警告は無害です。それらをきれいに無視するために(たとえば、すべてのクライアントの警告を無効にする必要はありません)、私はこのややハックなアプローチを使用しました:

-eveyone に含まれる protobuf.h ファイルのラッパー。(実際に生成された H ファイルは含まれません)

    #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)  

およびラッパーCファイル(実際のprotobuf CCファイルは私のプロジェクトにはありません->直接ビルドされていません)

#include "MyProtoFile_WRAPPER.h"  
#include "MyProtoFile.cc"
4

1 に答える 1