私たちは、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"