2012-02-16 3 views
1

プロジェクトを.net 3.5から.net 4.0に移行していて、次の問題に直面しました。両方の機能がうまく動作し、.NET 3.5の場合.NET 4.0でインポートされたネイティブ関数が動作しません

<DllImport("hid64.dll")> _ 
Public Sub GenerateHardwareID(_ 
     <MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> ByVal Buffer As Byte(), _ 
     ByVal BufferLength As Int32) 
End Sub 

<DllImport("hid64.dll")> _ 
Public Function BufferToString(_ 
     <MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> ByVal Buffer As Byte(), _ 
     ByVal BufferLength As Int32) As <MarshalAs(UnmanagedType.LPWStr)> String 
End Function 

: 2つのDLLIMPORT文があります。しかし、.NET 4.0では、BufferToString関数の呼び出しは例外を発生させることなく、プログラムの実行を中断します。
私はCallingConvention、CharSetなどでDllImport属性のフィールドを使いました。 http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx 成功しませんでした。

このバリアント:

<DllImport("hid64.dll", CharSet:=CharSet.Auto, PreserveSig:=False, SetLastError:=True)> _ 
Public Function BufferToString(_ 
     <MarshalAs(UnmanagedType.LPArray)> ByVal Buffer As Byte(), _ 
     ByVal BufferLength As Int32) As <MarshalAs(UnmanagedType.LPWStr)> String 
End Function 

は、プログラムの開発の実行を中断しませんが、機能は「何も」を返しません。

答えて

1

ここに私が最も可能性の高い説明と思われるものがあります。

BufferToString関数の戻り値は文字列です。 p/invoke marshallerは、それをネイティブから管理対象にマーシャリングする必要があります。これは、ネイティブコードがCOMアロケータによって割り当てられたNULL終端の文字ポインタを返すと仮定することによって行います。 .net文字列へのコンテンツの転送が終了すると、ポインタのCoTaskMemFreeが呼び出されます。そのメモリがCOMアロケータによって割り当てられなかった場合、この時点で障害が発生する可能性があります。

問題を回避するには、いくつかの選択肢があります。 BufferToStringのp/invokeを変更してIntPtrを返すことができます。内容をMarshal.PtrToStringUniの.net文字列にコピーします。これにより、管理されていないメモリを処分する責任があります。恐らく、アンマネージドライブラリはあなたにそれを行うための仕組みを提供しているでしょう。

アンマネージドライブラリを作成した場合は、代替ソリューションを使用できます。 p/invokeを現在のままにしておきますが、CoTaskMemAllocを使用して戻り値を割り当てるようにアンマネージドライブラリを変更してください。それはp/invokeのマーシャラーの前提と一致します。

+1

David、明確な説明をいただきありがとうございます。それは問題の解決です。 – KorVet

関連する問題