2

を使用して.NETオブジェクトのメンバー関数を呼び出したいと思いますcalli。次のコードを使用して、intを受け取り、intを正常に返す静的関数を呼び出すことができます。

// push the int argument
// push the address obtained using Ldftn
ilg.EmitCalli (OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.StdCall, typeof<int>, [|typeof<int>|])
// correct result now on stack 

次のようなものを使用して、intを受け取りintを返すメンバー関数を呼び出すことができると期待していました。Jason Bockによる「CILProgramming」は、おそらく間違って読んでいますが、うまくいくはずだと示唆しています。リフレクターはまた、何かが正しくないと考えており、呼び出しが難読化されていると主張しています。その最良の推測は" return (int) *ptr1(num1);"です。これは、静的呼び出しの場合と同じです。

ilg.Emit (OpCodes.Ldarg_0)            
// push the int argument
// push the address                                    
ilg.EmitCalli (OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.StdCall, typeof<int>, [|typeof<int>|])   

2番目のフラグメントを呼び出すと、次のメッセージが表示されます。言うまでもなく、私はマーシャリングなどを使用していません。

ランタイムで致命的なエラーが発生しました。エラーのアドレスは、スレッド0x20e50の0xed470d3fにありました。エラーコードは0xc0000005です。このエラーは、CLRのバグ、またはユーザーコードの安全でない部分または検証できない部分のバグである可能性があります。このバグの一般的な原因には、COM-interopまたはPInvokeのユーザーマーシャリングエラーがあり、スタックが破損する可能性があります。

私は何を間違っているのですか?

4

1 に答える 1

1

のドキュメントにcalliよると、使用しているオーバーロードは、EmitCalli()アンマネージコードを呼び出すためにのみ使用する必要があります。マネージコードの場合は、もう1つのパラメーターを受け取るオーバーロードを呼び出して、次のように設定する必要があります(非常にまれな、をnull使用している場合を除く)。varagrg

ilg.EmitCalli (OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.HasThis, typeof<int>, [|typeof<int>|], null)
于 2013-03-03T20:38:03.880 に答える