How do I read a uint from a pointer with Marshalli

2019-07-29 16:04发布

问题:

I have a native method which needs a pointer to write out a dword (uint).

Now I need to get the actual uint value from the (Int)pointer, but the Marshal class only has handy methods for reading (signed) integers.

How do I get the uint value from the pointer?

I've searched the questions (and Google), but couldn't really find what I needed.

Sample (not working) code:

IntPtr pdwSetting = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint)));

        try
        {
            // I'm trying to read the screen contrast here
            NativeMethods.JidaVgaGetContrast(_handleJida, pdwSetting);
            // this is not what I want, but close
            var contrast = Marshal.ReadInt32(pdwSetting);
        }
        finally
        {
            Marshal.FreeHGlobal(pdwSetting);
        }

The return value from the native function is a dword between 0 and 255 with 255 being full contrast.

回答1:

Depending on whether you may use usafe code you can even do:

static unsafe void Method()
{
    IntPtr pdwSetting = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint)));

    try
    {
        NativeMethods.JidaVgaGetContrast(_handleJida, pdwSetting);
        var contrast = *(uint*)pdwSetting;
    }
    finally
    {
        Marshal.FreeHGlobal(pdwSetting);
    }
}

Note, that a C++ function pointer like

void (*GetContrastPointer)(HANDLE handle, unsigned int* setting);

can be marshaled as

[DllImport("*.dll")]
void GetContrast(IntPtr handle, IntPtr setting); // most probably what you did

but also as

[DllImport("*.dll")]
void GetContrast(IntPtr handle, ref uint setting);

which lets you write code like

uint contrast = 0; // or some other invalid value
NativeMethods.JidaVgaGetContrast(_handleJida, ref contrast);

which is superior in both performance and readability.



回答2:

You can simply cast it to uint:

uint contrast = (uint)Marshal.ReadInt32(pdwSetting);

For example:

int i = -1;
uint j = (uint)i;
Console.WriteLine(j);

outputs 4294967295.



回答3:

Use the Marshal.PtrToStructure overload that takes an IntPtr and a type and pass in typeof(uint) - that ought to work!

Hope this helps!