【问题标题】:P/Invoke in C#, how to find out CallingConvention?C#中的P/Invoke,如何找出CallingConvention?
【发布时间】:2012-10-09 06:13:43
【问题描述】:

我将我的项目从 VS2005(针对 .net 2)更新到 VS2010(针对 .net4)。似乎pInvokeStackImbalance MDA 默认启用,然后我得到一堆"unbalanced the stack" 异常。以这个为例:

[DllImportAttribute("gdi32.dll")]
private static extern IntPtr CreateSolidBrush(BrushStyles enBrushStyle, int crColor);  

它在 .net 2 中工作,但现在它抛出异常。我把它改成了这个,它可以工作:

[DllImportAttribute("gdi32.dll", CallingConvention = CallingConvention.ThisCall)]
private static extern IntPtr CreateSolidBrush(BrushStyles enBrushStyle, int crColor);

令我惊讶的是,pinvoke.net 将其列为

[DllImport("gdi32.dll")]
static extern IntPtr CreateSolidBrush(uint crColor);

为什么我的老不工作?似乎 pinvoke.net 是错误的,但我如何找出哪个调用转换是给定一个 win32 函数?

编辑
我的项目使用来自C# Rubber Rectangle 的代码进行异或绘图。显然,代码需要修复才能在 .Net 4 中运行。

【问题讨论】:

    标签: c# winapi pinvoke


    【解决方案1】:

    CreateSolidBrush 使用 stdcall。几乎所有 Win32 API 都这样做。他们从不使用thiscall。函数声明为:

    HBRUSH CreateSolidBrush(
      __in  COLORREF crColor
    );
    

    所以你的错误只是你的版本有太多参数。您发现的 pinvoke.net 声明是正确的。

    stdcall 约定将参数从右向左推送,这解释了即使使用额外的虚假参数,您的代码也是如何工作的。

    【讨论】:

    • 你怎么知道是stdcall?该链接没有说明任何内容。
    • API 函数总是如此。如果您在头文件中查找它,您会看到它声明为WINAPI,其计算结果为__stdcall。极少数是__cdecl,因为它们具有可变数量的参数。例如wsprintf。 API 文档将始终显式调用 __cdecl API 函数。
    • 谢谢!不敢相信方法签名一直都是错误的!!
    • 显然您传递的enBrushStyle 参数被忽略了。只能想知道您的版本来自哪里! ;-)
    • 是的,他们弄错了。当然,应该很明显看到该函数名为 CreateSolidBrush。样式是名称的一部分。无论如何,现在一切都清楚了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-08
    • 1970-01-01
    • 2010-09-14
    • 1970-01-01
    • 2013-05-31
    相关资源
    最近更新 更多