0

C dll からエクスポートされた次の関数があります。

// C
BOOL WINAPI GetAttributeValue(
        IN     TAG                      * psTag, 
        IN     DWORD                      dwEltIdx,
        IN     DWORD                      dwAttrIdx,
        OUT    BYTE                     * pbBuffer,
        IN OUT DWORD                    * pdwLen )

// C#
[DllImport(Simulator.ASSEMBLY, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public extern static int GetAttributeValue(
        IntPtr tag_id,
        int element_index,
        int attribute_index,
        [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=4)]
        byte[] data_buffer,
        [In, Out]
        ref int data_length
    );

これは、SOに関するいくつかの回答に基づいて、私がそれを使用しようとしている方法です:

int result = -1;
byte[] buffer = new byte[2048];
int length = buffer.Length;

result = Simulator.GetAttributeValue(
        tag.NativeId,
        element_index,
        attribute_index,
        buffer,
        ref length
    );

int[] output = new int[length];

for (int i = 0; i < length; i++)
{
    output[i] = buffer[i];
}

return output;

私が試したもう1つのことは、これもSOで見つかった回答に基づいています:

[DllImport(Simulator.ASSEMBLY, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public extern static int GetAttributeValue(
        IntPtr tag_id,
        int element_index,
        int attribute_index,
        IntPtr data_buffer, // changed this
        [In, Out]
        ref int data_length
    );

// snip

GCHandle pinned_array = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr pointer = pinned_array.AddrOfPinnedObject();

result = Simulator.GetAttributeValue(
        tag.NativeId,
        element_index,
        attribute_index,
        pointer,
        ref length
    );

// snip, copying stuff to output

pinned_array.Free();
return output;

どちらの場合も、 mylengthは正しく入力されているように見えますが、buffer常に空のままです。私は P/Invoke とマーシャリングに精通していないので、これが正しいかどうかはわかりません。これを行うより良い方法はありますか?

4

1 に答える 1

1

どちらのバージョンも問題なく、何が問題なのかを推測するのは困難です。正しくシミュレートしていない「シミュレーター」のようなクワック。タグ ID の IntPtr が奇数です。エラーコードを受け取ったときに例外をスローするなど、結果に対して合理的なことを行う必要があります。

バッファを渡す必要がある AC 関数は一般的に面倒です。正しいバッファ サイズを推測する必要があります。2048 を選択することは十分に期待できる推測ですが、推測が低すぎるとうまくいきません。このような関数の一般的なプロトコルは、2 回呼び出す必要があることです。最初に の値をdata_length0 のように意図的に低くします。その後、関数はエラー コードを返し、data_length必要なバッファ サイズに設定します。次に、正しいサイズのバッファーで再度呼び出します。これは単なる推測であり、問​​題に適合します。

于 2013-10-24T21:27:59.293 に答える