C# Interop - 如何传递可由 C 作为结构数组访问的 C# 结构

C# Interop - How to pass a C# struct that can be accessed by C as an array of structs

我目前正在尝试让非托管 (c) DLL 在我的 C# 应用程序中工作。我遇到的问题是将结构传递给非托管函数。

我已经像这样导入了函数(使用 PInvoke 互操作助手)...

[System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint = "ListDevices")]
public static extern int ListDevices(ref Device_t devices, ref int DevicesCount);

我要传递的结构...

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
    public struct Device_t
    {
        /// int
        public int Address;

        /// int
        public int GearAddress;

        /// int
        public int Id;

        /// char[8]
        [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 8)]
        public string Rev;
    }

DLL代码中的函数(无关代码已删除)...

static int listDevices(Device_t *devices, int *deviceCount)
{
    char *pch;
    int i;
    char *token;
    int paramCount;
    Device_t device;

    // code removed //

    while (token != NULL)
        {
            pch = strstr(token, "ENTRY");
            if (pch != NULL)
            {
                paramCount = sscanf(&token[0], "%*d ..... %d",        
                &device.Address, &device.GearAddress, &device.Rev, 
                &device.Id);
                if (paramCount == 4)
                {
                    devices[i].Address = device.Address;
                    devices[i].GearAddress = device.GearAddress;
                    devices[i].Id = device.Id;
                    strcpy(devices[i].Rev, device.Rev);
                    i++;
                }
            }
            token = strtok(NULL, "#");
        }

    // code removed //
}

主要问题是 c 代码将 'Device_t devices' 变量作为数组访问,但 c# 函数只接受单数 Device_t。 我相信结构中存在一个字符串使其不可 blittable,使事情进一步复杂化:(

理想情况下,我希望能够在 c# 中声明一个 Device_t 的数组,它可以被 c 访问,但是我知道数组在 c# 中的结构与 c 不同。

我发现了问题,这是我编组 DLL 函数的方式。

需要指定 In 和 Out 属性。

[System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint = "ListDevices")]
public static extern int ListDevices([In, Out] Device_t[] devices, ref int DevicesCount);