[英]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: 两个常见原因:
stdcall
. stdcall
。 Perhaps the native code uses cdecl
. cdecl
。 Try adding CallingConvention=CallingConvention.Cdecl
to the DllImport
attribute. CallingConvention=CallingConvention.Cdecl
添加到DllImport
属性。 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.