Should DWORD map to int or uint?
Asked Answered
P

7

36

When translating the Windows API (including data types) into P/Invoke, should I replace DWORD with int or uint?

It's normally unsigned, but I see people using int everywhere instead (is it just because of the CLS warning? even the .NET Framework itself does this), and so I'm never really sure which one is the correct one to use.

Privet answered 17/7, 2011 at 17:34 Comment(0)
B
48

Well according to the MSDN DWORD is an unsigned integer with a range of 0 to 4294967295.

So ideally you should replace it with uint rather than int.

However, as you have spotted uint is non-CLS compliant so if your method is publicly visible you should use int and do the conversion. The corollary to that is that if your method isn't used outside your assembly you should mark it as internal rather than public. Then you'll be able use a uint.

Brazee answered 17/7, 2011 at 17:38 Comment(1)
I guess what worries me is that it's (1) inconsistent with the framework, and (2) non-CLS-compliant. Should I just ignore that?Privet
I
2

It's unsigned so map it to uint.

Istic answered 17/7, 2011 at 17:38 Comment(0)
L
1

A DWORD is, by (Microsoft's) definition, an unsigned 32-bit integer. It should map to whichever type your compiler uses to represent that.

These days it's most likely an unsigned int, but that's not a portable implementation. I know you're using C#, but to give you an example in a language I'm more familiar with, a typical implementation in C might be:

#if defined(SOME_HARDWARE_IMPLEMENTATION)
#define DWORD unsigned int
#elif #defined(SOME_OTHER_IMPLEMENTATION)
#define DWORD unsigned long
#elif #defined(YET_ANOTHER_IMPLEMENTATION)
#define DWORD something_else
#else
#error Unsupported hardware; cannot map DWORD
#endif
Laundress answered 17/7, 2011 at 17:38 Comment(2)
However, in C#, uint and int are 32-bit integers. You are correct, though, that in C, primitive data types such as int and long are not consistent between compilers. This, however, will only be an issue here if DWORD is used in a function or API not defined by Microsoft, where by its definition, DWORD is a 32-bit unsigned integer.Chengteh
C int and long are always 32 bit on windowsIstic
C
1

The CLS compliance warning applies only if the P/Invoke method is visible outside the assembly, which generally means the call is public. If the method is not externally visible, then it is acceptable to use uint.

Chengteh answered 17/7, 2011 at 17:39 Comment(0)
M
1

Use int. Reason being, if I change "AutoRestartShell" with a uint variable:

regKey.SetValue("AutoRestartShell", uintVariable);

the data type in the Registry Editor changes to "REG_SZ". If I ask for that value to be returned with:

regKey.GetValue("AutoRestartShell");

a string gets returned.

If, however, I change "AutoRestartShell" with an int variable:

regKey.SetValue("AutoRestartShell", intVariable);

The data type stays as "REG_DWORD".

Why does this happen? No idea. All I know is that it does. Logic certainly would tell us that uint should be used but that changes the data type which we don't want.

Manns answered 17/3, 2017 at 17:34 Comment(3)
How does the behaviour or a completely unrelated part of .NET relate to marshalling a WinApi type?Shabbir
For the same reason that two apps cannot communicate with each other by one sending integers where the other expects strings and vice versa. As for whether or not uint or int would make an actual difference here, I don't know. It was just an observation. I figured it was best to not change what doesn't need to be changed.Manns
It looks like the culprit is the private CalculateValueKind method. It simply doesn't acknowledge uint, but also doesn't know short or other numeric types. But I see the point - public API should handle CLS-compliant types more importantly than non-CLS-compliant types. The CLR actually doesn't differentiate between an int and uint.Shabbir
V
1

According to official Platform invoke data types mapping table DWORD corresponds to System.UInt32 in C#.

Visitor answered 29/3, 2020 at 19:40 Comment(0)
F
0

Sadly,read Registry must use int otherwise throw exception.this microsoft code:

private static void Get45or451FromRegistry()
{
    using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\")) {
        if (ndpKey != null && ndpKey.GetValue("Release") != null) {
            Console.WriteLine("Version: " + CheckFor45DotVersion((int) ndpKey.GetValue("Release")));
        }
      else {
         Console.WriteLine("Version 4.5 or later is not detected.");
      } 
    }
}

although release is REG_DWORD

Flowerdeluce answered 12/10, 2017 at 2:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.