A P/Invoke mystery [modified]
-
A few days ago, I looked through a C# program that didn't run well on x64 system. Finally I fixed it, but faced a mysterious fact. First, I had suspected that its P/Invoke declarations are wrong, and found the one like this.
// MEMORY_BASIC_INFORMATION is defined separately.
[DllImport("kernel32.dll")]
static extern int VirtualQuery(IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);I thought it was surely incorrect. The native definition of the function is like this...
SIZE_T WINAPI VirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
...and SIZE_T is platform dependent, so that its corresponding P/Invoke declaration might be like this.
[DllImport("kernel32.dll")]
static extern IntPtr VirtualQuery(IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, IntPtr dwLength);But the thing confused me is that the function itseif seemd to run well even on x64 system. I think that 'incorrect' one runs well because dwLength is passed with a register (not stack) on x64 system. If the parameter is 64bit or less, it would be passed apparently. Does somebody have an idea about it?
modified on Monday, August 2, 2010 10:07 PM
-
A few days ago, I looked through a C# program that didn't run well on x64 system. Finally I fixed it, but faced a mysterious fact. First, I had suspected that its P/Invoke declarations are wrong, and found the one like this.
// MEMORY_BASIC_INFORMATION is defined separately.
[DllImport("kernel32.dll")]
static extern int VirtualQuery(IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);I thought it was surely incorrect. The native definition of the function is like this...
SIZE_T WINAPI VirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
...and SIZE_T is platform dependent, so that its corresponding P/Invoke declaration might be like this.
[DllImport("kernel32.dll")]
static extern IntPtr VirtualQuery(IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, IntPtr dwLength);But the thing confused me is that the function itseif seemd to run well even on x64 system. I think that 'incorrect' one runs well because dwLength is passed with a register (not stack) on x64 system. If the parameter is 64bit or less, it would be passed apparently. Does somebody have an idea about it?
modified on Monday, August 2, 2010 10:07 PM
Tsuda Kageyu wrote:
because dwLength is passed with a register (not stack) on x64 system.
That contradicts the WINAPI calling convention in the declaration, so I'd be surprised if that was the case.
-
Tsuda Kageyu wrote:
because dwLength is passed with a register (not stack) on x64 system.
That contradicts the WINAPI calling convention in the declaration, so I'd be surprised if that was the case.
Electron Shepherd wrote:
That contradicts the WINAPI calling convention
I think it's not a contradiction. The calling convention on x64 system is different from the ones on x86 system. Here is the overview about it. http://msdn.microsoft.com/en-us/library/ms235286%28VS.80%29.aspx[^]
-
Electron Shepherd wrote:
That contradicts the WINAPI calling convention
I think it's not a contradiction. The calling convention on x64 system is different from the ones on x86 system. Here is the overview about it. http://msdn.microsoft.com/en-us/library/ms235286%28VS.80%29.aspx[^]
Tsuda Kageyu wrote:
The calling convention on x64 system is different from the ones on x86 system.
Interesting. I didn't know that - thanks.
-
Electron Shepherd wrote:
That contradicts the WINAPI calling convention
I think it's not a contradiction. The calling convention on x64 system is different from the ones on x86 system. Here is the overview about it. http://msdn.microsoft.com/en-us/library/ms235286%28VS.80%29.aspx[^]
Good piece of information. Not doing anything with 64-bits yet, but I'll tuck this away in memory for when that day comes.
Regards David R --------------------------------------------------------------- "Every program eventually becomes rococo, and then rubble." - Alan Perlis The only valid measurement of code quality: WTFs/minute.
-
A few days ago, I looked through a C# program that didn't run well on x64 system. Finally I fixed it, but faced a mysterious fact. First, I had suspected that its P/Invoke declarations are wrong, and found the one like this.
// MEMORY_BASIC_INFORMATION is defined separately.
[DllImport("kernel32.dll")]
static extern int VirtualQuery(IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);I thought it was surely incorrect. The native definition of the function is like this...
SIZE_T WINAPI VirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
...and SIZE_T is platform dependent, so that its corresponding P/Invoke declaration might be like this.
[DllImport("kernel32.dll")]
static extern IntPtr VirtualQuery(IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, IntPtr dwLength);But the thing confused me is that the function itseif seemd to run well even on x64 system. I think that 'incorrect' one runs well because dwLength is passed with a register (not stack) on x64 system. If the parameter is 64bit or less, it would be passed apparently. Does somebody have an idea about it?
modified on Monday, August 2, 2010 10:07 PM
Was the C# caller compiled as 32 bit by any chance?
Regards, Nish
Blog: blog.voidnish.com Most recent article: An MVVM friendly approach to adding system menu entries in a WPF application
-
Was the C# caller compiled as 32 bit by any chance?
Regards, Nish
Blog: blog.voidnish.com Most recent article: An MVVM friendly approach to adding system menu entries in a WPF application
No. I made doubly sure that the process was running in x64 mode. By the way, your articles have helped me much for years. Thanks :-D
-
A few days ago, I looked through a C# program that didn't run well on x64 system. Finally I fixed it, but faced a mysterious fact. First, I had suspected that its P/Invoke declarations are wrong, and found the one like this.
// MEMORY_BASIC_INFORMATION is defined separately.
[DllImport("kernel32.dll")]
static extern int VirtualQuery(IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);I thought it was surely incorrect. The native definition of the function is like this...
SIZE_T WINAPI VirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
...and SIZE_T is platform dependent, so that its corresponding P/Invoke declaration might be like this.
[DllImport("kernel32.dll")]
static extern IntPtr VirtualQuery(IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, IntPtr dwLength);But the thing confused me is that the function itseif seemd to run well even on x64 system. I think that 'incorrect' one runs well because dwLength is passed with a register (not stack) on x64 system. If the parameter is 64bit or less, it would be passed apparently. Does somebody have an idea about it?
modified on Monday, August 2, 2010 10:07 PM
Yeah really weird
-
Yeah really weird
Always use
System.Runtime.InteropServices.Marshal.SizeOf
method to ensure platform independency.With great code, comes great complexity, so keep it simple stupid...:-\ :-\