質問

私はこのマーシャルを倒すのに本当に苦労しています。

私は次のように見えるウーマネージコードを持っています:

WORD HLP_GetDeviceNames (LPSTR *DevNames, WORD Max_Len, WORD Max_Num)

ちょうど参照私はこの管理されていないコードを書いていませんでしたが、それを使用する必要があります。

返品:エラーを示す単語。

devnames:char配列の配列へのポインタ。基本的に、変更されて私に戻ってくる一連の文字列!

max_len:各文字列の長さ(これは256でなければならないと言われています)

max_num:配列の長さ。私は機能している別の呼び出しコールを使用しています。これは私に数のデバイスを教えてくれるので、送信する文字列の数を正確に知っています。

P/Interop Interop SignatureToolkitを使用して、これをたくさん把握しましたが、さらに進むために束を読んでいます。私が今ここにいる場所:

[DllImport("UsbMeasLib.dll")]
public static extern ushort HLP_GetDeviceNames([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)] ref StringBuilder[] DevNames, ushort Max_Len, ushort Max_Num);

私は自分のコードをこのように呼びます:

StringBuilder[] DevNames = new StringBuilder[deviceCount];
     for(int i = 0; i< deviceCount; i++)
     {
           DevNames[i] = new StringBuilder().Append(' ', 256);
     }

     HachUsbMeasLib.HLP_GetDeviceNames(ref DevNames, 256, Convert.ToUInt16(DevNames.Count())); 

String Builder Arrayを使用しています。なぜなら、文字列がマイートできないため、新しい文字列を返すことができるように、文字列ビルダーを変更するために管理されていないコードが必要だからです。

コードを実行すると、配列が変更されていません!

何が起こっているのか本当にわかりませんが、CLRが配列を設置しないように管理していないコードを伝えることと関係があると思いますが、代わりに新しいリファレンス(Pointer)を作成します。たとえそうであっても、私はそれを修正する方法を知りません。

誰でも提供できる洞察をありがとう!

役に立ちましたか?

解決 2

私はこれを理解しました。答えてくれた人に感謝します。

私はそれがどのように機能するかを知りました。私は単にメモリスペースを供給するだけですが、このオブジェクトに内外に出入りすることをマーシャリングに知らせなければなりません。そうすれば、管理されていないコードが割り当てられたスペースを変更できるようにします。

私はこのようにやった:

[DllImport("UsbMeasLib.dll")]
private static extern ushort HLP_GetDeviceNames([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)] string[] DevNames, ushort Max_Len, ushort Max_Num);

管理されていないコードは、問題のない文字列を単純に置き換えるため、文字列ビルダーの代わりに文字列を使用します。変更された文字列ではなく、配列ポインターを取り戻しています。管理されたコードは、新しい文字列オブジェクトを指すようにポインターの配列を変更するだけです(私は思う)。

int numDev = HLP_GetNumDevices();


string[] names = new string[numDev];

for (int i = 0; i < names.Length; i++)
{
    names[i] = new StringBuilder().Append(' ', 256).ToString();
}

ushort errorCode = HLP_GetDeviceNames(names, 256, Convert.ToUInt16(numDev));

未amangのコードにメモリを割り当て、管理されていないコードに文字列をそこに追いかけます。

これは機能しますが、潜在的なメモリリークやその他の潜在的な問題があるかどうかはわかりません。

他のヒント

低レベルで作業してみてください。 devNamesパラメーターをintptr []として宣言します。次の方法で準備してください。

IntPtr[] devNames = new IntPtr[deviceCount];

for(int i = 0; i < deviceCount; i++) 
{ 
    devNames[i] = Marshal.AllocHGlobal[256];
}

この配列をhlp_getdevicenamesに渡します。出力データを処理するには、Marshal.PtrtoStringansiをすべてのDevNamesメンバーに適用します。最終的にMarshal.FreehglobalでDevNames [i]をリリースすることを忘れないでください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top