2009-08-19 14 views
1

私はVisual Studioアドインを作成しており、管理されているCodeElementsオブジェクトをアンマネージ形式にマーシャリングする必要があります。私はそれをキャストして、管理されていない側のCodeElementのように扱うことができるので、ポインタをメモリに必要とするだけです。C#でIntPtrにCodeElementsをマーシャリングする

[DllImport("CodeMethodsToString.dll")] 
    private static extern BSTR* CodeMethodsToString(void* functionObject); 

    public static void CodeMethodsToXML(XmlElement parent, CodeElements elements) 
    { 
     //Call CodeMethodsToString: how do I marshall CodeElements to an IntPtr? 
     //set XmlElement in here 
    } 

私はXMLに対処する方法を知っており、私はこれをC#で動作させています。再帰の最低レベルでさまざまなメンバー変数をすべて呼び出すと、プログラムの速度が低下するため、アンマネージDLLを作成しました。私は単純にSystem.Runtime.Interop.Marshalを使用してCodeElementsオブジェクトをメモリ内のCOMオブジェクトへのポインタに変換する方法を知る必要があります。

ありがとうございました。

+0

DTBが答えに近いようだが、していないようですポインタを正しくマーシャリングします。オブジェクト参照がオブジェクトのインスタンスまたは保護されたメモリエラーに設定されていない場合でも、マーシャリングで何かを変更する必要があります。 – user142350

答えて

3

はルックス:RCWはので、ここでそれを行うためのコードである、あなたのために(私はそれが意志ほぼ確実だ)ことを行います場合、私は覚えていないことができます。

[DllImport("CodeMethodsToString.dll")] 
[return: MarshalAs(UnmanagedType.BStr)] 
private static extern string CodeMethodsToString(IntPtr functionObject); 

public static void CodeMethodsToXML(XmlElement parent, CodeElements elements) 
{ 
    GCHandle pin; 
    try 
    { 
     pin = GcHandle.Alloc(elements, GCHandleType.Pinned); 
     string methods = CodeMethodsToString(pin.AddrOfPinnedObject()); 
    } 
    finally 
    { 
     pin.Free(); 
    } 
} 
+0

これは方法です。 GCがポインタを動かさないようにオブジェクトを固定することは、回避する必要があり、AcessViolationExceptionです。 –

+0

私は混乱しています - 私はこれを私のテストハーネスで動作させることはできません。 CodeElements型ではないRCWのGCHandle.AllocでArgumentExceptionが発生します。 Visual StudioのCodeElementsはTLBImped COMインターフェイスではありませんか? –

+0

@Kimあなたの答えにDoStuffの実装をテストしていますか? – scottm

1

CodeElementsa ComVisibleインターフェイスであり、GuidAttributeを持っていますか?

そして、C#はあなたのためのCOMオブジェクトのマーシャリングを行います、そしてあなたは、単に引数の型としてCodeElementsを使用することができます。

[DllImport("example.dll")] 
private static extern void DoStuff(CodeElements codeElements); 
+1

それはそれほど単純ではないことを恐れる: CodeElements is abstract。私はオブジェクトへのポインタが必要になります。どうすればそれを得ることができますか? – user142350

+1

明確にする:このデフォルトマーシャリングを行っているとき、値渡しですか?それはマーシャリングをマーシャリングし、ポインタを渡すだけの方法ですか? – user142350

+0

参照渡しです。私は "CodeElements"がこれを参照していると仮定します:http://msdn.microsoft.com/en-us/library/envdte.codeelements.aspxしたがって、私の例だけで動作するはずです。そうでない場合は、エラーの詳細を投稿してください。 – dtb

1

とすぐに、あなたはrefにそれを変換することによって開始する必要がありますスターやアンパサンドを見るように(安全なバージョンのポインタ)。私は過去に、REFキーワードを使用する場合、参照型は魔法の作業を開始する持っていた(非常に矛盾している - しかし、私はそれがそれらの相互運用のものの一つだと思う):

[DllImport("example.dll")] 
private static extern void DoStuff(ref CodeElements codeElements); 

あなたはまた、試みることができる:

[DllImport("example.dll")] 
private static extern void DoStuff([In, Out] ref CodeElements codeElements); 

または、これらの属性の順列の1つ。

あなたが試してみたいかもしれないものは、COMライブラリを作るのにMFCを使用することです(私はC++以来ずっと長いことでした)。ネイティブコールexport the thing as a type libraryを使用せず、Visual Studioで参照として追加してください(はい、簡単です)。したがって、あなたのようなもので、最大着陸する予定:

myCoolClass.DoStuff(codeElements); 

また、(あなたは固定する必要がある場合、それはエラーが断続的になります)、それを固定することができます。ジョナサンが近かったよう

GCHandle handle = new GCHandle(); 
try 
{ 
    handle = GCHandle.Alloc(fooz, GCHandleType.Pinned); 
    // Use fooz. 
} 
finally 
{ 
    if (handle.IsAllocated) 
    handle.Free(); 
} 
+2

値ではなく参照で値の型(たとえば 'struct ')を渡す場合は、' ref'が使用されます。 'CodeElements'はCOMインターフェース、すなわち参照型であるため、常に参照渡しされます。 – dtb

+1

これを試してもうまくいきませんでした。私がやっている他のマーシャルのいくつかの組み合わせでうまくいくかもしれません。これらのキーワードの1つが関連している可能性があることを思い出してくれてありがとう。 – user142350

+1

@dtb - 読む!それは過去に変化をもたらしたと言いました。生成されたMSILは同一ではなく、interopレイヤでキーワードが適切に表示される可能性があります。 .Netの純粋な.Net呼び出しでは、合意しても効果はありません。 –

1

オプションで、記事の最後に例をチェックアウトすることができます::これは私がそれを行うだろう方法です GCHandle MSDN

関連する問題