简体   繁体   中英

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

I'm currently trying to get an unmanaged (c) DLL to work in my c# application. The problem I am having is passing a struct into an unmanaged function.

I have imported the function like so (using PInvoke Interop Assistant)...

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

The struct I am trying to pass...

[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;
    }

The function in the DLL code (irrelevant code removed)...

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 //
}

The main issue is that the c code accesses the 'Device_t devices' variable as an array, but the c# function only accepts a singular Device_t. I believe the presence of a string in the struct makes it non-blittable, complicating things further :(

Ideally I want to be able to declare an array of Device_t in c# that can be accessed by c, however I'm aware arrays are structured differently in c# compared to c.

I found the issue, it was the way I was marshaling the DLL function.

Both the In and Out attributes needed to be specified.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM