C# 在.NET 4中使用IntPtr时出现PinVokesTack异常?(在.NET 3.5中工作)

C# 在.NET 4中使用IntPtr时出现PinVokesTack异常?(在.NET 3.5中工作),c#,.net,c#-4.0,c#-3.0,intptr,C#,.net,C# 4.0,C# 3.0,Intptr,这可能是一个很难回答的问题,但在过去的几个小时(或几天)里,这件事让我陷入了困境 我在.NETFramework4.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, X

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

我在.NETFramework4.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)
然而,当我在.NET4.0中运行这个程序时,我得到了一个p/INVOKE错误,然而。。。在3.5中运行此操作不会触发此错误。在我和另一个程序员检查了代码之后,我们似乎把它归结为在4.0上运行不同的IntPtr

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

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

任何想法都非常感谢

汤姆

更新:

本地声明:

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

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

在我的脑海中,您是否检查了这两个项目的细节?如果一个是64位,另一个是32位,则会出现错误。请注意,在最新版本中,C#项目的默认值从任何CPU更改为x86。这在x86操作系统上并不重要,但在x64操作系统上,这会产生显著的差异


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

这有两个常见原因:

  • 调用约定不匹配。您的C代码使用默认的
    stdcall
    。本机代码可能使用
    cdecl
    。尝试将
    CallingConvention=CallingConvention.Cdecl
    添加到
    DllImport
    属性中
  • 参数列表不匹配(见下文)
  • 不要自欺欺人地认为你的代码是正确的,因为.NET3.5没有引发这个错误。NET4中的错误检测更好,这就是为什么您只能在那里看到错误。但是您的代码在所有.net版本中都被破坏了


    < >您的C++虚拟方法的本机定义为:

    virtual ErrCode XCamera::GetFrame(FrameType type, unsigned long ulFlags, 
        void * buffer, unsigned int size);
    
    看起来您正在将对象指针作为pinvoke调用中的第一个参数传递。我认为这是可行的,尽管我对导出时如何处理虚拟函数的了解还不够,不知道这是否是一个问题。大概您已经导出了一个普通的C函数来实例化对象


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

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

    virtualerrcode XCamera::GetFrame(FrameType类型,无符号长字符串,void*缓冲区,无符号整数大小)

    具有与以下项相对应的.NET类型:
    FrameType、uint、IntPtr、uint


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

    XC#u GetFrame的本机定义是什么,您遇到的错误是什么?请解释您得到的错误是什么?定义:virtual ErrCode XCamera::GetFrame(FrameType类型,无符号长字符串,void*缓冲区,无符号整数大小)[纯虚拟]错误是PINVOKE堆栈Imabalance:调用PINVOKE函数“DLLTest!DLLTest.Form1::XC_GetFrame”使堆栈不平衡。您的代码在.net 2中已经有一个错误的导入签名,但该版本过于宽松,出现了某些错误。net 4更为严格,公开(而不是导致)错误。两个项目都在32位下运行,所有关联的DLL也在32位下运行…调试时我收到的错误是:PinVokeStackDistribution:调用PInvoke函数“DLLTest!DLLTest.Form1::XC_GetFrame”使堆栈不平衡。这可能是因为托管PInvoke签名与非托管目标不匹配签名。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。函数定义:virtual ErrCode XCamera::GetFrame(FrameType类型,无符号长ulFlags,void*缓冲区,无符号整数大小)[纯虚拟]不可能是这样。当有一点不匹配时,您无法调用函数。@DavidHeffernan:由于缺少错误消息,我不确定其他DLL何时会加载到内存中。将调用约定添加到DLLImport属性中,仍然得到相同的错误。我列出了本机函数声明吗n在另一个答案中是否正确?另外,如果框架设置为3.5,应用程序将正常运行,但正如您所说的,代码可能会被破坏。更新原始帖子以包含声明:)我猜想使用PInvoke调用与:使用System.Runtime.InteropServices?当你调用一个带有DllImport属性的函数时,那就是pinvoke.Updated ulflags以键入uint,但是这个应用程序中从同一个DLL调用的其他方法仍然有效;我很确定是C++方法……HyDA6963我想我已经把它讲过头了。我怀疑您可以通过p援引调用C++方法。除了通过必须导出的帮助器函数之外,您不能实例化C++对象。我想你已经这么做了。我真的不知道虚拟方法是如何与pinvoke一起工作的。你…吗?否则,您需要修复长时间的不匹配,并使调用约定正确。