You don’t need to ask me a question the compiler can answer more accurately


A customer reported having problems developing the correct p/invoke signature for the INPUT structure. "The code works on 32-bit machines, but on 64-bit machines, the call to Send­Input returns ERROR_INVALID_PARAMETER." The sample code included the lines

INPUT[] inputs = new INPUT[1];
inputs[0].type = INPUT_KEYBOARD;
...
int size = Marshal.SizeOf(inputs[0]);
if (!SendInput(1, ref inputs, size))
{
 Console.WriteLine("Failed with error {0}", GetLastError());
}

My response was simply, "I bet you are passing the wrong structure size. Note that on 64-bit Windows, the alignment of the inner structures is 8-byte rather than 4-byte. Write a C++ program that does the same thing and compare."

The customer decided to read only the first sentence of my reply, possibly the second, and ignore the third. "So what size should the INPUT structure be on 64-bit machines?"

There are a few ways you can go about finding out the size of a structure.

One method is to ask Raymond. This may work, but it makes Raymond rather grumpy since it demonstrates that you are lazy and just want the answer handed to you with no effort (or demonstration of understanding) on your part.

Another method is to sit down with the structure definition and work out the size on a piece of paper, bearing in mind that various #pragma pack directives can change how the structure packing is applied.

But the easiest way to get the size of a structure is to use the sizeof operator, because that is after all the method the compiler uses. To get the same value as the C++ compiler, just ask the C++ compiler!

#include <windows.h>
#include <stdio.h>
#include <stddef.h>

int __cdecl main(int argc, char **argv)
{
 printf("the size is %d\n", sizeof(INPUT));
 printf("the offset of mi is %d\n", offsetof(INPUT, mi));
 return 0;
}

You can now use this amazing technique to answer wolf550e's question:

SSE types require 16-byte alignment. I guess they aren't used in the Windows SDK? How about directX or something where they are used?

Comments (11)
  1. Anonymous says:

    I use this technique quite a bit.

    Normally I'd ask how to call a function pointer obtained via interop in VB .NET but Raymond sounds grouchy today.

  2. Anonymous says:

    Some people are C++phobic. I wish there was an easy way to fix that, but I know when I'm not working on a C++ project I'd normally find it easier to calculate the structure size myself than open the C++ compiler.

  3. Anonymous says:

    I don't understand this — I don't write in C++ or C# much, but I see that even the erroneous code is already using SizeOf.  What am I missing?

  4. Anonymous says:

    Of course, this is the wrong question. Marshal.SizeOf would give the right answer, if their managed definition of the INPUT struct were correct. And if it's not, passing a different size will just make it harder to debug (actually, it'll probably just cause an access violation).

    The size being wrong is just a side effect.

  5. SimonRev says:

    I agree with Random382 — you need to fix the structure itself at which point Marshal.SizeOf will return the right value.  Of course the associated C++ code can give some nice hints as to what you did wrong, so there is value there.

  6. Anonymous says:

    Joshua: Marshal.GetDelegateForFunctionPointer.

  7. Anonymous says:

    There is another way to find out the size by ask Raymond without making Raymond grumpy – search on the web for what Raymond said:

    pinvoke.net/…/user32.sendinput

    [The customer got the incorrect declaration from that web page. (It has since been fixed, but if you go through the archives, you'll see that it was wrong in the past.) -Raymond]
  8. Anonymous says:

    "This may work, but it makes Raymond rather grumpy" – yes, but you should be aware that there's an entire cadre of people here who relish the thought of making Raymond grumpy. My evidence, such as it is, is the continuing practice by some people of doing things that Raymond has already stated he doesn't like :-)

  9. Anonymous says:

    I don't even bother writing a program to print the size anymore. I just attach to a process that compiles with the structure I want to test (usually you have a process like this, or otherwise you wound't be interested) and ask the debugger to print the sizeof() the structure.

  10. Anonymous says:

    Since a .NET programmer (be it in VB.NET or C#) doesn't need to know how to write program in C++ (for example, I don't know how to write a program beyond the console program level students were taught to write in school… :P), I'd say I'm not surprised to see the customer ignore the third part.

    Actually if this were a paid support request or the question is asked in these managed newsgroups, I'd expect direct answer be supplied too.

Comments are closed.