0

I have a third-party unmanaged dll I am trying to use from a C# application via PInvoke. The relevant parts of the unmanaged code are as follows:

unsigned char WINAPI GetDeviceInfo(PDEVICES pDevInfo, unsigned int *retError = NULL);

typedef struct _tag_DEVICE_INFO{
    unsigned int dev_Index;
    wchar_t dev_MakerName[256];         // Maker Name
    unsigned int dev_MakerName_Length;
    wchar_t dev_ModelName[256];         // Model Name
    unsigned int dev_ModelName_Length;
}DEVICE_INFO,*PDEVICE_INFO;

typedef struct _tag_DEVICES{
    unsigned int Device_Count;          // Number of devices detected
    wchar_t *Device_IDs[512];
    DEVICE_INFO Device_Info[512];       // Detected device information: Maximum 256
}DEVICES,*PDEVICES;

My C# code is this:

using System;
using System.Runtime.InteropServices;

namespace scratch
{
    class Program
    {
        [DllImport("Lmxptpif.dll", SetLastError = true)]
        public static extern byte GetDeviceInfo([In, Out, MarshalAs(UnmanagedType.LPStruct)] DEVICES pDevInfo, out uint retError);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct DEVICE_INFO
        {
            public uint dev_Index;
            public string dev_MakerName;        // Maker Name
            public uint dev_MakerName_Length;
            public string dev_ModelName;        // Model Name
            public uint dev_ModelName_Length;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct DEVICES
        {
            [MarshalAs(UnmanagedType.U4)]
            public uint Device_Count;          // Number of devices detected
            [MarshalAs(UnmanagedType.ByValArray, SizeConst=512, ArraySubType=UnmanagedType.LPWStr)]
            public string[] Device_IDs;            // Array of Device IDs (512 PWSTRs)
            public DEVICE_INFO[] Device_Info;
        }


        static void Main(string[] args)
        {
            uint retError = 0;
            DEVICES pInfo = new DEVICES();
            byte result = GetDeviceInfo(pInfo, out retError);
            if (result == 1 && retError == 0)
            {
                string models = "";
                for (int i = 0; i < pInfo.Device_Count; i++)
                {
                    models += pInfo.ToString();
                }
            }
        }
    }
}

When I run the code, the call to GetDeviceInfo() throws the exception:

System.Runtime.InteropServices.MarshallDirectiveException: 'Cannot marshal 'parameter #1': Invalid managed/unmananged type combination (this value type must be paired with Struct).'

I don't understand what the error message is trying to tell me.

What is the correct way to define the 'struct's and the enternal function declaration? How can I fix this so the function call succeeds?

JNygrenLT
  • 173
  • 12
  • Does https://stackoverflow.com/questions/10076214/invalid-managed-unmanaged-type-combination-with-embedded-dynamically-allocated answer your question? – Athanasios Kataras Oct 05 '20 at 15:15
  • See pinvoke : http://www.pinvoke.net/default.aspx/user32.GetRawInputDeviceList – jdweng Oct 05 '20 at 15:21
  • Very awkward, lots of bugs. First argument must be `ref DEVICES`. All the arrays require ByvalArray, the strings must be char[]. Device_IDs[] must be IntPtr[], marshal if not IntPtr.Zero with Marshal.PtrToStringUni(). – Hans Passant Oct 05 '20 at 15:22

0 Answers0