マネージド (C#) コードとアンマネージド (C++) コードの間で多くの通信を行うアプリケーションがあります。Visual Studio 2005 (!) を使用しており、tlbimp によって自動的に生成された相互運用アセンブリを使用しています。
単純な構造体を関数の引数としてやり取りすることはかなり幸運です。また、オブジェクトは非常に単純であるため、IRecordInfo インターフェイスを使用してそれらを SAFEARRAY にパックできます。これらの配列を引数として COM メソッドに渡すと、適切に機能するようです。
可変長配列を UDT に埋め込むことができるようにしたいと考えていますが、うまくいきません。誰かがこれをどのように達成したかを示すドキュメントを 1 つも見つけることができなかったと思います。また、それができないというドキュメントも見つかりませんでした。
1) 単純なアプローチ: マネージ コードでセーフ配列を宣言するだけです。
struct MyUdt {
int member1;
BSTR member2;
SAFEARRAY *m3;
};
C++ コンパイラはこれで問題ありませんが、生成された IDL は tblimp.exe を混乱させます。メンバー m3 の署名とメンバー tagSAFEARRAY.rgsabound の署名を変換できないことが報告されています。これらは単なる警告ですが、意味があり、結果のアセンブリは使用できません。
奇妙なことに、LPSAFEARRAY を使用すると、さまざまな方法で失敗しますが、同じ理由で、tblimp では対処できません。
2)トリッキー:バリアントにパックします:
struct MyUdt {
int member1;
BSTR member2;
VARIANT m3;
};
UDT の safearray を構築するコードがあり、それによって問題が発生することはありません。基本的にはMSDNからコピーされています。そのコードを使用して safearray を作成すると、次のようになります。
pVal->m3.vt = VT_SAFEARRAY | VT_RECORD;
pval->parray = p;
奇妙な方法で失敗します。それは常に壊れます、いくつかのバリエーションは OutOFMemoryException を生成します...奇妙で、他のバリエーションはさまざまな方法で失敗します。(ここで pRecInfo ポインターが必要かどうかはわかりませんが、存在するかどうかにかかわらず、同じように失敗します。)
このための Google 検索スペースは、私が尋ねていない質問への回答でひどく汚染されています。
- アンマネージ コードから UDT/構造体を渡す方法を教えてください。
- 構造体の SAFEARRAY をどのように渡しますか? (私たちはこれをうまくやっています。)
- p/invoke またはカスタマー マーシャリングを使用して UDT を渡す方法を教えてください。
そして、管理されていない側ではなく、管理されている側から物事を定義する方法を説明する多くの回答。
また、初期バージョンの .NET における VT_RECORD の問題について説明している Microsoft KB がいくつかあります。私はこれらが密接に関連しているとは思わない - VT_RECORD タイプは VARIANT と SAFEARRAY で動作する。(しかし、UDT マーシャリングではそうではないかもしれません...)
これが機能しない場合は、少なくともその理由を知っておくとよいでしょう。
- マーク