28

私はC++で次の構造体を持っています:

#define MAXCHARS 15

typedef struct 
{
    char data[MAXCHARS];
    int prob[MAXCHARS];
} LPRData;

そして、これらの構造体の 3 つの配列を取得するために p/invoking している関数:

void GetData(LPRData *data);

C++ では、次のようにします。

LPRData *Results;
Results = (LPRData *)malloc(MAXRESULTS*sizeof(LPRData));
GetData( Results );

それは問題なく動作しますが、C# では動作しないようです。次のような C# 構造体を作成しました。

public struct LPRData
{

    /// char[15]
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
    public string data;

    /// int[15]
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)]
    public int[] prob;
}

そして、それらのうちの 3 つの配列 (およびそのすべてのサブ配列) を初期化し、これに渡すと:

GetData(LPRData[] data);

成功して戻りますが、LPRData 配列のデータは変更されていません。

LPRData の 3 つのサイズの生のバイト配列を作成し、それを次のような関数プロトタイプに渡すことさえ試みました。

GetData (バイト [] データ);

しかし、その場合、最初の LPRData 構造から「データ」文字列を取得しますが、同じ LPRData からの「prob」配列を含め、その後は何も取得しません。

これを適切に処理する方法のアイデアはありますか?

4

5 に答える 5

25

構造体宣言にいくつかの属性を追加してみます

[StructLayout(LayoutKind.Sequential, Size=TotalBytesInStruct),Serializable]
public struct LPRData
{
/// char[15]
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
public string data;

/// int[15]
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)]
public int[] prob;
}

*注 TotalBytesInStruct は変数を表すことを意図したものではありません

JaredPar も正しいですが、IntPtr クラスを使用すると役立つ可能性がありますが、PInvoke を使用してからかなり時間が経っているため、錆びています。

于 2008-10-09T17:54:03.180 に答える
13

ポインターを扱うときの 1 つのトリックは、IntPtr を使用することです。次に、ポインターで Marshal.PtrToStructure を使用し、構造体のサイズに基づいてインクリメントして結果を取得できます。

static extern void GetData([Out] out IntPtr ptr);

LPRData[] GetData()
{
    IntPtr value;
    LPRData[] array = new LPRData[3];
    GetData(out value);
    for (int i = 0; i < array.Length; i++)
    {
        array[i] = Marshal.PtrToStructure(value, typeof(LPRData));
        value += Marshal.SizeOf(typeof(LPRData));
    }
    return array;
}
于 2008-10-09T17:50:38.740 に答える
4

この質問で同様のトピックが議論され、結論の 1 つは、CharSet名前付きパラメーターを に設定する必要があるというものでしたCharSet.Ansi。そうしないと、wchar_t配列ではなく配列を作成することになりますchar。したがって、正しいコードは次のようになります。

[Serializable]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct LPRData
{
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
    public string data;

    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)]
    public int[] prob;
}
于 2012-02-08T07:20:29.230 に答える
3

PInvoke Interop Assistant が役立つ場合があります。http://clrinterop.codeplex.com/releases/view/14120

于 2008-10-16T02:37:45.057 に答える
2

GetData パラメータをOutAttributeでマークしましたか?

InAttribute と OutAttribute の組み合わせは、配列や書式設定された blittable でない型に適用する場合に特に便利です。両方の属性を適用した場合にのみ、呼び出し先がこれらの型に加えた変更が呼び出し元に表示されます。

于 2008-10-18T21:42:40.797 に答える