我如何马歇尔指向结构数组的指针?马歇尔、数组、指针、结构

2023-09-03 05:15:13 作者:放肆嘚寂寞只因爲你

我的C declerations如下:

My C declerations are as follows:

int myData(uint myHandle, tchar *dataName, long *Time, uint *maxData, DATASTRUCT **data);

typedef struct {
  byte Rel;
  __int64 Time;
  char Validated;
  unsigned char Data[1];
} DATASTRUCT ;

我的C#declerations如下:

My C# declerations are as follows:

[DllImportAttribute("myData.dll", EntryPoint = "myData")]
        public static extern int myData(uint myHandle, [MarshalAs(UnmanagedType.LPTStr)] string dataName, out long Time, out uint maxData, ref DATASTRUCT[] data);

[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct DATASTRUCT
{
    public sbyte Rel;
    public long Time;
    public byte Validated;
    public double Data;
}

我再调用管理功能如下:

I then call the managed function as follows:

string dataToShow = "description";
long Time;
uint maxData; // How many structs will be returned, i.e. how much data is available
uint myHandle = 1;

DATASTRUCT [] dataInformation = new DATASTRUCT[3]; //doesn't matter what i specify as the array size?

myData(myHandle, dataToShow, out Time, out maxData, ref dataInformation);

在执行上述功能将即使有3返回成功返回仅用一个结构。为什么会这样?

Upon execution the above function will return successfully with only one structure even though there are 3 to return. Why is this so?

更多的信息;我试图通过指针结构数组通过以下方式指针:

Additional information; I have tried passing the pointer to a pointer of an array of structs the following ways:

- ref DATASTRUCT[] data; //Works but only returns one struct
- [Out, MarshalAs(UnmanagedType.LPArray)] DATASTRUCT[] data; //returns the number of defined structs with garbage

据我了解我可能需要使用的IntPtr 做一些手工编组,然而,我不知道如何实现这一因此任何的建议是AP preciated 。

As I understand it I might need to do some manual marshalling using IntPtr, I however do not know how to implement this so any advise would be appreciated.

感谢您

推荐答案

好了,它好像你的本地库不分配,所以真的,所有你需要做的是提供一个指针,通过它可以访问分配的数据。

Okay, it seems as though your native library does the allocation, so really all you need to do is provide a pointer through which you can access the allocated data.

更改您的API定义(注意,我改变了MAXDATA参数为uint,长为64位.NET和32位原生。

Change your API definition to (note, I changed the maxData param to uint, long is 64 bits in .NET and 32 bits in native.

[DllImportAttribute("myData.dll", EntryPoint = "myData")]
public static extern int myData(uint myHandle, [MarshalAs(UnmanagedType.LPTStr)] string dataName, out uint Time, out uint maxData, out IntPtr pData);

关闭我的头顶,我不太记得,如果你需要的了关键字的最后一个参数,但我认为是这样。

Off the top of my head I can't quite remember if you need the out keyword for the final parameter, but I think so.

然后,调用myData的:

Then, call myData:

uint nAllocs = 0, time = 0;
IntPtr pAllocs = IntPtr.Zero;
myData(1, "description", out time, out nAllocs, out pAllocs);

现在,pAllocs应指向非托管内存,元帅到这些托管的内存是不是太困难的:

Now, pAllocs should point to unmanaged memory, to marshal these into managed memory isn't too difficult:

[StructLayoutAttribute(LayoutKind.Sequential, Pack = 1)]
public struct DATASTRUCT
{
    public byte Rel;
    public long Time;
    public byte Validated;
    public IntPtr Data; //pointer to unmanaged string.
}


int szStruct = Marshal.SizeOf(typeof(DATASTRUCT));
DATASTRUCT[] localStructs = new DATASTRUCT[nAllocs];
for(uint i = 0; i < nallocs; i++)
    localStructs[i] = (DATASTRUCT)Marshal.PtrToStructure(new IntPtr(pAllocs.ToInt32() + (szStruct * i)), typeof(DATASTRUCT));

现在,你应该有当地的结构数组。

And now you should have an array of local structs.

要注意的一点 您可能需要设置你的项目编译为86,到一个IntPtr的尺寸标准化为4个字节(DWORD),而不是值为anycpu默认的8。

A point to note You may need to set your project to compile as x86, to standardize the size of an IntPtr to 4 bytes (DWORD) instead of AnyCPU's default 8.