2011-07-28 40 views
4

現在、C++からC#への戻り値としてSAFEARRAY(GUID)を渡す必要があるという問題が発生しています。GUIDのCOM SAFEARRAYがC++からC#に返される

現在、C#側では、Tlbimp.exe(タイプライブラリインポータ)から生成されたInterop DLLが使用されています。

IDLがある:私も試した

HRESULT GetGuids(
    [out]SAFEARRAY(GUID)* guids); 

[うち、RETVAL]

関数シグネチャは次のとおり

HRESULT 
WINAPI 
MyClass::GetGuids(SAFEARRAY** guids) 

IがSafeArrayCreate()又はSafeArrayCreateVector()を使用する場合:

SAFEARRAY* psa 
psa = SafeArrayCreate(VT_CLSID, 1, rgsabound); 

NULL SAFEARRAYポインタを取得します。これは、E_OUTOFMEMORYが正しくないことを示すはずです。 http://poi.apache.org/apidocs/org/apache/poi/hpsf/Variant.htmlそのは、CLSIDが

であることが示された私はまたしてセーフ配列を構築する別の手段を試してみた:私が見つけた何

VT_CLSIDが唯一のOLEプロパティセット用ではないSAFEARRAYのことだった SafeArrayAllocDescriptor()SafeArrayAllocData()

hResult = SafeArrayAllocDescriptor(1, guids) 
hResult = SafeArrayAllocData(*guids); 

これは私は、配列を作成することができますが、SafeArrayPutElement()とそれを取り込むとき、私は(パラメータが正しくありません)0x80070057がのHRESULTを取得します。これは、それは私がSafeArrayAccessData()

GUID* pData = NULL; 
hResult = SafeArrayAccessData(*guids, (void**)&pData); 

を手動で取り込むことができます

同様 VT_CLSIDパラメータを取りますが、私はC#の側からエラーを取得するという事実におそらくある: 「値が収まっていません予想される範囲 "

SAFEARRAY(GUID)をC#にretvalまたはoutパラメータで返す機能をどのように達成するかはわかりません。

私はすでにUDTやマーシャリングなしでGUIDを渡している多くの領域がIDLにあります。私はSAFEARRAYでそれらを渡す必要があるまですべてがうまく動作します。事前

答えて

3

すべてのヘルプは高く評価され、 おかげであなたは絶対的に正しいです - 問題はVT_CLSIDがVARIANTまたはSAFEARRAYのいずれかで許可されていないことです。それは、オートメーションと互換性のあるタイプではないGUIDにまで沸き立っています。

多くの場合、同じことをやってみる必要があります。問題を回避する最も簡単な方法は、GUIDを文字列に変換し、SAFEARRAY(VT_BSTR)を渡すことです。この変換を行うには多少穀物に逆らっていますが、とにかくマーシャリングが行われているという見方をすることができます。この変換はマーシャリングの一種です。

+0

おかげmscorlib.tlbで定義された:: mscorlib独自のタイプライブラリ内のGUIDと同じメモリレイアウトを持つ構造体を作成し、または使用するようにしているので、これを実行する方法はありません?私はすでにこのスタイルを使用しているので、可能であると考えました: 'HRESULT SendGuid( \t \t [in] GUID guid);'単一のGUIDを渡すidlの多くの場所で。私は本当にインターフェイスの純度を維持したいと考えていました。それは、単に文字列を使用することを避けるためのはるかに契約的なものです:( – Steve

+0

私は同意し、自分自身でそれをやりたいと思います。しかし、それは不可能です。 SAFEARRAYとVARIANTはこのAutomationサブセットに含まれていますが、VT_CLSIDはありませんSendGuid(GUID)メソッドはAutomationと互換性がありませんが、まだ完璧なCOMです。 SAFEARRAYタイプを使用して価格を支払うとすぐに、インターフェースがオートメーションと互換性がないようにしてください。 –

2

GUIDをUDT(ユーザー定義型)として渡す方法です。

このため、SafeArrayCreateExで初期化されるSAFEARRAYのVT_RECORD要素を使用します。しかしまず、タイプを記述できるIRecordInfoへのポインタを取得する必要があります。

GUIDはWindows/COMヘッダーで定義されており、uuidが関連付けられていないため、IRecordInfoインターフェイスを取得するために別のものを使用する必要があります。基本的には、2つのオプションがGUIDが

#import <mscorlib.tlb> no_namespace named_guids 

IRecordInfo* pRecordInfo = NULL; 
GetRecordInfoFromGuids(LIBID_mscorlib, 1, 0, 0, __uuidof(Guid), &pRecordInfo); 

SafeArrayCreateEx(VT_RECORD, 1, &sab, pRecordInfo);