1

このマーシャリングをダウンさせるのに本当に苦労しています。

次のような umanaged コードがあります。

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

参考までに、私はこのアンマネージ コードを作成していませんが、使用する必要があります。

戻り値: エラーを示す WORD。

DevNames: char 配列の配列へのポインター。基本的に、変更されて返される文字列の配列です!

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

Max_Num: 配列の長さ。デバイスの数を教えてくれる別の Invoke 呼び出しを使用しているので、送信する文字列の数が正確にわかります。

私は P/Invoke 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())); 

文字列は変更できないため、新しい文字列を返すことができるように、文字列ビルダーを変更するアンマネージ コードが必要なため、文字列ビルダー配列を使用しています。

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

何が起こっているのかよくわかりませんが、配列をその場で変更せず、代わりに新しい参照(ポインター)を作成するようにアンマネージコードに指示するCLRと関係があると思います。これが事実であっても、それを修正する方法がわかりません。

誰でも提供できる洞察に感謝します!

4

2 に答える 2

2

低レベルで作業してみてください。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] をリリースすることを忘れないでください。

于 2010-08-16T15:33:09.787 に答える
0

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

私はそれがどのように機能するかを知りました。私はメモリ空間を提供するだけですが、アンマネージ コードが割り当てられた空間を変更できるように、このオブジェクトの出入りを期待していることをマーシャリングに知らせる必要があります。

私はこのようにしました:

[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));

アンマネージ コードにメモリを割り当ててから、アンマネージ コードがそこで文字列を変更できるようにします。

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

于 2010-08-17T18:15:48.943 に答える