简体   繁体   English

在.NET 4中使用IntPtr时出现PInvokeStackImbalance异常? (适用于.NET 3.5)

[英]PInvokeStackImbalance exception when using IntPtr in .NET 4? (Works in .NET 3.5)

Might be a bit of noob question but it's something that's been getting me in a pickle for the past few hours (or days)... 可能会有一点菜鸟的问题,但这是让我在过去几个小时(或几天)的泡菜中得到的东西......

I'm calling a method from a DLL in my code in .NET Framework 4.0 我在.NET Framework 4.0的代码中调用DLL中的方法

  [DllImport("xeneth.dll")]
    public static extern ErrorCode XC_GetFrame(Int32 h, FrameType type, ulong ulFlags, IntPtr buff, uint size);

and then using it here: 然后在这里使用它:

if (XC_GetFrame(myCam, XC_GetFrameType(myCam), 0, IntPtr.Zero, (uint)fs) != ErrorCode.E_NO_FRAME)

However, when I run this in .NET 4.0 I get a P/INVOKE error, however... running this in 3.5 does not trigger this error. 但是,当我在.NET 4.0中运行它时,我得到一个P / INVOKE错误,但是......在3.5中运行它不会触发此错误。 After myself and another programmer have gone over the code we seem to have put it down to the IntPtr running differently on 4.0. 在我和另一个程序员完成代码之后,我们似乎把它归结为在4.0上运行不同的IntPtr。

My application needs to run in .NET 4.0 as a couple of features required by the application are only available in 4.0 ... 我的应用程序需要在.NET 4.0中运行,因为应用程序所需的一些功能仅在4.0中可用...

Is there anything that maybe i'm overlooking or have simply forgotten to include? 有什么可能我忽略或只是忘记包括?

Any thoughts are much appreciated! 任何想法都非常感谢!

Tom 汤姆

Update: 更新:

Native Declaration: 土着宣言:

virtual ErrCode XCamera::GetFrame(FrameType type, unsigned long ulFlags, void *buffer, unsigned int size)

Error: A call to PInvoke function 'DLLTest!DLLTest.Form1::XC_GetFrameType' has unbalanced the stack. 错误:对PInvoke函数'DLLTest!DLLTest.Form1 :: XC_GetFrameType'的调用使堆栈失衡。 This is likely because the managed PInvoke signature does not match the unmanaged target signature. 这很可能是因为托管PInvoke签名与非托管目标签名不匹配。 Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature. 检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

Two common causes for this: 两个常见原因:

  1. Mismatch of calling conventions. 调用约定不匹配。 Your C# code uses the default of stdcall . 您的C#代码使用默认的stdcall Perhaps the native code uses cdecl . 也许本机代码使用cdecl Try adding CallingConvention=CallingConvention.Cdecl to the DllImport attribute. 尝试将CallingConvention=CallingConvention.Cdecl添加到DllImport属性。
  2. Mismatch of parameter lists (see below). 参数列表不匹配(见下文)。

Don't kid yourself that your code is alright because .net 3.5 doesn't raise this error. 不要嘲笑你的代码是正常的,因为.net 3.5不会引发这个错误。 The error detection in .net 4 is better which is why you only see the errors there. .net 4中的错误检测更好,这就是为什么你只看到那里的错误。 But your code is broken in all .net versions. 但是你的代码在所有.net版本中都被破坏了。


The native definition for your C++ virtual method is: C ++虚拟方法的本机定义是:

virtual ErrCode XCamera::GetFrame(FrameType type, unsigned long ulFlags, 
    void * buffer, unsigned int size);

It looks like you are passing the object pointer as the first parameter in your pinvoke call. 看起来您正在将对象指针作为pinvoke调用中的第一个参数传递。 I think that could work, although I don't know enough about how virtual functions are handled when exported to know whether that's a problem. 我认为这可行,虽然我不太了解在导出时如何处理虚函数以了解这是否是一个问题。 Presumably you have exported a plain C function to instantiate objects. 据推测,您已导出一个普通的C函数来实例化对象。

The other problem that I see is that on Windows, C/C++ long is 32 bits. 我看到的另一个问题是在Windows上,C / C ++ long是32位。 AC# long is 64 bits. AC# long是64位。 This means that the correct declaration for ulFlags is as uint in your C# code. 这意味着ulFlags的正确声明在C#代码中是uint

Off the top of my head have you checked the bit-ness of both projects? 在我的脑海中,您是否检查了两个项目的位置? You will get errors if one is 64-bit and the other is 32-bit. 如果一个是64位而另一个是32位,则会出错。 Note that in a recent version the default for C# projects changed from Any CPU to x86. 请注意,在最近的版本中,C#项目的默认值从Any CPU更改为x86。 That won't matter on a x86 OS, but on x64 OSes it makes a significant difference. 这在x86操作系统上无关紧要,但在x64操作系统上它会产生重大影响。

Additionally you should generally include as much of the text of the error as you can, censoring to protect private information is fine, but the error number and text can be quite helpful. 此外,您通常应尽可能多地包含错误文本,审查以保护私人信息是正常的,但错误号和文本可能非常有用。 Additionally when working with extern it is helpful to include both definitions of any struct types to ensure they are equivalent. 此外,在使用extern时,包含任何struct类型的两个定义以确保它们是等效的是有帮助的。 (Another common problem). (另一个常见问题)。

Maybe a better question is why it worked before. 也许一个更好的问题是它之前有效的原因。 The declaration you provided: 您提供的声明:

virtual ErrCode XCamera::GetFrame(FrameType type, unsigned long ulFlags, void * buffer, unsigned int size)

has .NET types corresponding to: FrameType, uint, IntPtr, uint . .NET类型对应于: FrameType, uint, IntPtr, uint

On Windows, unsigned long is a 32-bit type, while in C# ulong is a 64-bit type. 在Windows上, unsigned long是32位类型,而在C# ulong是64位类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM