28

我在 C++ 中有以下结构:

#define MAXCHARS 15

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

以及我正在调用/调用的函数以获取其中 3 个结构的数组:

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 数组中的数据没有改变。

我什至尝试创建一个大小为 3 个 LPRData 的原始字节数组,并将其传递给这样的函数原型:

获取数据(字节 [] 数据);

但在这种情况下,我将从第一个 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

处理指针时的一个技巧是只使用 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

在这个问题上讨论了一个类似的主题,其中一个结论是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 互操作助手可能会有所帮助。http://clrinterop.codeplex.com/releases/view/14120

于 2008-10-16T02:37:45.057 回答
2

您是否使用OutAttribute标记了 GetData 参数?

将 InAttribute 和 OutAttribute 结合起来在应用于数组和格式化的非 blittable 类型时特别有用。只有当您同时应用这两个属性时,调用者才能看到被调用者对这些类型所做的更改。

于 2008-10-18T21:42:40.797 回答