A.dllがB.dllを参照する2つのc++/ cli dll(つまり、/ clrでコンパイルされたもの)があります。アセンブリBには、メソッドGetMgdClassBがあり、アセンブリAから呼び出したいと思います。アセンブリB(B.cpp)のコードは次のとおりです。
namespace B
{
public class NativeClassB
{
public:
NativeClassB();
// ...
};
public ref class MgdClassB
{
public:
static MgdClassB ^ GetMgdClassB(const std::vector<NativeClassB *> & vecNativeBs)
{
// ...
vecNativeBs;
return gcnew MgdClassB();
}
};
}
GetMgdClassBメソッドがstd::vectorをとることに注意してください。アセンブリAでは、次のコード(A.cpp)を使用してこのメソッドを呼び出そうとしています。
namespace B
{
class NativeClassB;
}
#pragma make_public(std::vector<B::NativeClassB *>)
namespace A
{
void Foo()
{
std::vector<B::NativeClassB *> vecNativeBs;
B::MgdClassB::GetMgdClassB(vecNativeBs);
}
}
A.cppをコンパイルすると、次のエラーが発生します。
error C2158: 'std::vector<_Ty>' : #pragma make_public directive is currently supported for native non-template types only
このプラグマを追加したかった理由は、ネイティブ型がデフォルトでアセンブリに対してプライベートであるためです。プラグマを削除すると、次のエラーが発生します(予想どおり)。
error C3767: 'B::MgdClassB::GetMgdClassB': candidate function(s) not accessible
テンプレートのインスタンス化タイプstd::vector<B::NativeClassB *>はアセンブリ専用であるためです。
試みられた解決策
1. void *を使用し、タイプセーフティを解除します。
メソッドを変更して、GetMgdClassBを取得しvoid *、のアドレスをstd::vector<NativeClassB *>メソッドに渡します。でGetMgdClassB。その後static_cast、に渡すvoid *ことができstd::vector<NativeClassB *> *ます。もちろん、これは機能しますが、型の安全性を損ないます。
2. NativeClassBのマネージラッパーを作成し、マネージコンテナを渡します
マネージドクラスを作成します。たとえばref class NativeClassBWrapper、ネイティブのNativeClassBへの参照を保持することが唯一の目的であるとします。GetMgdClassBを変更して、NativeClassBWrappersの管理対象コンテナーを取得します(例List<NativeClassBWrapper ^> ^)。これには、GetMgdClassBを呼び出す前に新しいマネージドコンテナーを作成してデータを設定する必要があり、マネージドクラスB内で、ネイティブコンテナーに再パッケージ化する必要があるという欠点がありますstd::vector<NativeClassB *>(Bのコードはこのタイプを処理するため)。
現在、私はソリューション#1を採用する傾向にあります。これは、(a)パフォーマンスの問題が発生せず、(b)これを実行するのはごく一部の場合のみであるためです。型の安全性を失うのは好きではありませんが、ネイティブテンプレートのインスタンス化型を表示するコンパイラの機能が現在不足していることを考えると、それは正当なことのようです。
質問:
より良い回避策はありますか?