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

本文关键字:NET 异常 适用于 PInvokeStackImbalance IntPtr | 更新日期: 2023-09-27 18:29:07

这可能是个小问题,但在过去的几个小时(或几天)里,这件事一直让我陷入困境。。。

我正在从.NET Framework 4.0 中的代码中的DLL调用一个方法

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

然后在这里使用:

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

然而,当我在.NET 4.0中运行此程序时,我会收到p/INVOKE错误,然而。。。在3.5中运行此操作不会触发此错误。在我和另一位程序员仔细研究了代码之后,我们似乎把它归结为IntPtr在4.0上以不同的方式运行。

我的应用程序需要在.NET 4.0中运行,因为该应用程序所需的一些功能仅在4.0中可用…

有没有什么东西可能是我忽略了,或者只是忘记了包括在内?

任何想法都非常感谢!

Tom

更新:

原住民声明:

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

错误:调用PInvoke函数的DLLTest!DLLTest.Form1::XC_GetFrameType"使堆栈不平衡。这可能是因为托管PInvoke签名与非托管目标签名不匹配。请检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

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

造成这种情况的两个常见原因:

  1. 调用约定不匹配。您的C#代码使用默认值stdcall。也许本机代码使用cdecl。尝试将CallingConvention=CallingConvention.Cdecl添加到DllImport属性中
  2. 参数列表不匹配(见下文)

不要自欺欺人地认为你的代码是好的,因为.net 3.5不会引发这个错误。.net 4中的错误检测更好,这就是为什么你只在那里看到错误的原因。但是你的代码在所有的.net版本中都被破坏了。


C++虚拟方法的本机定义是:

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

看起来您正在将对象指针作为pinvoke调用中的第一个参数进行传递。我认为这是可行的,尽管我对导出时如何处理虚拟函数还不够了解,不知道这是否是个问题。假设您已经导出了一个普通的C函数来实例化对象。

我看到的另一个问题是,在Windows上,C/C++long是32位。一个C#long是64位。这意味着ulFlags的正确声明是C#代码中的uint

你检查过这两个项目的细节了吗?如果一个是64位,另一个是32位,则会出现错误。请注意,在最近的版本中,C#项目的默认值从AnyCPU更改为x86。这在x86操作系统上并不重要,但在x64操作系统上会有很大的不同。

此外,你通常应该尽可能多地包含错误的文本,审查以保护私人信息是可以的,但错误编号和文本可能会很有帮助。此外,当使用extern时,包含任何struct类型的两个定义以确保它们是等效的是很有帮助的。(另一个常见问题)。

也许更好的问题是为什么它以前有效。您提供的声明:

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

具有与FrameType, uint, IntPtr, uint相对应的.NET类型。

在Windows上,unsigned long是32位类型,而在C#中,ulong是64位类型。