2011-02-14 68 views
1

我是P /在gdi32.dll中调用CreateRectRgn。此功能的正常的P/Invoke签名是:Win 7 x64上的奇怪P /调用问题

[DllImport("gdi32", SetLastError=true)] 
static extern IntPtr CreateRectRgn(int nLeft, int nTop, int nRight, int nBottom); 

作为快捷方式,我也定义了这个过载:

[DllImport("gdi32", SetLastError=true)] 
static extern IntPtr CreateRectRgn(RECT rc); 

[StructLayout(LayoutKind.Sequential)] 
struct RECT{ 
    public int left; 
    public int top; 
    public int right; 
    public int bottom; 
} 

(是的,我知道CreateRectRgnIndirect,但由于我必须使用函数来在System.Drawing.Rectangle和这个RECT结构之间进行转换,因此上述对我更有用,因为它不涉及中间变量。)

此重载应该与正常签名相同,因为它应该使堆栈处于相同的状态,输入为CreateRectRgn。事实上,在32位的Windows XP上,它的工作原理完美无瑕。但在Windows 7,64位上,该函数返回零,而Marshal.GetLastWin32Error()返回87,即“该参数不正确。”

任何想法可能是什么问题?

回答

1

哦。 Microsoft在x64上使用的调用约定是来自STDCALL的totally different。在对CreateRectRgn的调用中,堆栈根本不用于参数,它们都被传入寄存器。当我尝试通过一个RECT结构时,它会在堆栈上复制一个结构,并将一个指向这个副本的指针放入一个寄存器中。因此,这个小技巧在64位Windows中完全不起作用。现在我必须通过我所有的互操作代码,并找到其他地方,我已经完成了这些,并把它们全部拿出来。