2012-04-25 10 views
0

としてIオブジェクトの配列を渡し、C位からアンマネージC関数を呼び出すためにP /呼び出しを使用しているのマーシャリング。 アンマネージドコードでは、IUnknown for IDispatchをクエリします。 これは単純なケースでは機能しますが、オブジェクトの1つが配列そのものであれば、IDispatchの取得に失敗します。管理ツーアンマネージ「オブジェクトは[]」のIUnknown

[DllImport("NativeDll.dll")] 
    static extern void TakesAnObjectArray(int len, 
     [MarshalAs(UnmanagedType.LPArray, 
     ArraySubType = UnmanagedType.IUnknown)]object[] a); 

    public static void exec1(int a, object b, string c) 
    { 
     Object[] info_array; 
     Object[] parameters_array; 

     parameters_array = new object[4]; 
     parameters_array[0] = a; 
     parameters_array[1] = b; 
     parameters_array[2] = c; 
     parameters_array[3] = 55; 
     // THIS WORKS GREAT 
     TakesAnObjectArray(4, parameters_array); 

     info_array = new object[6]; 
     info_array[0] = parameters_array; 
     // THIS DOESN'T 
     // I CAN'T GET IDISPATCH FOR THE 1ST 'OBJECT' 
     TakesAnObjectArray(6, info_array); 
    } 

アンマネージコード:

void TakesAnObjectArray(int len, LPUNKNOWN p[]) 
    { 
     HRESULT hr; 
     for (int i=0; i<len; i++) 
     { 
      IDispatch *disp = NULL; 
      hr = p[i]->QueryInterface(IID_IDispatch, (void**)&disp); 
     } 
    } 

のQueryInterfaceは、ほとんどの時間を成功する

は、マネージコードを。 しかし、管理対象オブジェクトが実際に 'System.Object []'である場合、私はIDispatchインターフェイスを取得できません(hr = 0x80004002 = E_NOINTERFACE = 'このようなインターフェイスはサポートされていません')。

これを修正する何らかの方法でMarshalAs(...)を使用できますか? またはこれを動作させる別の方法はありますか?興味深いの

答えて

2

種類は、CLRは全くスニペット作業の最初の部分を作るために管理していることを確認します。 System.Array型が[ComVisible(true)]なので、おそらくIDispatchポインタを生成することができました。したがって、QIを動作させることはできますが、Arrayクラスのメンバーについて詳しく知ることなく、実際にIDispatchポインタを使って行うことはできません。宣言にCLRに配列要素をマーシャリングさせるものがないので、2番目のスニペットで不足していました。

あなたはこの正しい方法を修正する必要があります

は、配列は、COMオートメーションでのIDispatchオブジェクトではありません。 Object []の既定のCOMマーシャリングは、要素がVARIANTである安全な配列であるSAFEARRAY *です。 TakesAnObjectArray引数の型をLPUNKNOWN []からSAFEARRAY *に変更します。 [MarshalAs]属性を付けずに、pinvoke宣言を単純なオブジェクト[]に変更します。

あなたは、配列の要素にアクセスするには、C++のコードをSafeArrayLock()とSafeArrayGetElement()を使用する必要があります。 2番目のスニペットは、最初の要素がSAFEARRAY自体を含むVARIANTであるため、余分な間接化が必要です。

+0

コメントありがとうございました。 IUnknownで実際に管理していたのは、型名を取得するためにIDispatchを取得し、typeInfo-> GetDocumentation()というITypeInfoを取得しました。次に、 'GetIDsOfNames'と 'Invoke'を使用して 'ToString'を実行し、正しい情報を取得しました。 SAFEARRAYアプローチを試してみましょう。 – zvikam

+0

Cool。 SAFEARRAYとしてのマーシャリングが機能し、メインアレイとサブアレイのすべての要素が得られました。 さらに詳しい情報を問い合わせることができる複雑なオブジェクトに対して、私はVARIANTのVT_UNKNOWNを取得しました。 – zvikam

関連する問題