3

私は C/C++ プログラマーですが、デバイスと通信するために C# で記述されたプログラムを更新するように依頼されました。C# に関する私の知識は非常に基本的なものです。

以前のバージョンはすべて C# で記述されていましたが、実際にデバイスにアクセスする API が C に変更されました。C 関数の API を次のようにインポートできることがわかりました。

[DllImport("myapi.dll")]
public static extern int myfunct( 
                                 [MarshalAs(UnmanagedType.LPTStr)] string lpDeviceName,
                                 IntPtr hpDevice);

C では、この関数プロトタイプは次のとおりです。

int myFunct( LPTStr lpDeviceName, HANDLE* hpDevice );

HANDLE は次のように定義されます。

typedef void *HANDLE;

ただし、この機能は期待どおりには機能しません。実際、C# コード呼び出しでは、どのような型を宣言して C# メソッドに渡す必要があるのでしょうか?

助けてくれてありがとう。愚かな質問でごめんなさい。

4

2 に答える 2

4

実際、これはマーシャリングの間違った方法ですHANDLE *。動作しますが、例外が発生した場合は信頼できません。

あなたが投稿した関数は、オブジェクト作成関数のように見えます (hpDevice出力パラメーターとして扱われ、intステータス結果を返します)。

それをマーシャリングする正しい方法は、作成するオブジェクトのタイプとそれを閉じる方法によって異なります。HANDLEが呼び出しによって閉じられていると仮定するとCloseHandle(これはほとんどのオブジェクトに当てはまりますが、すべての HANDLEオブジェクトには当てはまりません)、おそらく から継承した型の 1 つを使用できますSafeHandleZeroOrMinusOneIsInvalid。たとえば、オブジェクトがレジストリ キーの場合は、SafeRegistryHandle;を使用します。ファイルの場合は、を使用しますSafeFileHandle

既存のセーフ ハンドル型がない (ただしCloseHandle、それを閉じるために使用する) 型の場合は、 から派生した独自のセーフ ハンドル型を定義する必要がありますSafeHandleZeroOrMinusOneIsInvalid。それを閉じるために使用しない型の場合はCloseHandle、から派生した独自のセーフ ハンドル型を定義する必要がありますSafeHandle

正しいSafeHandle派生型を決定したら、関数呼び出しでそれを使用できます (SafeFileHandle例として使用)。

[DllImport("myapi.dll")]
public static extern int myFunct(
    [MarshalAs(UnmanagedType.LPTStr)] string lpDeviceName,
    out SafeFileHandle hpDevice);
于 2010-07-16T13:04:38.497 に答える
1

ref IntPtr の代わりに IntPtr を渡している場合、定義は次のようになります。

[DllImport("myapi.dll")]
public static extern int myfunct( 
    [MarshalAs(UnmanagedType.LPTStr)] string lpDeviceName,
    ref IntPtr hpDevice);
于 2010-07-16T13:00:58.937 に答える