【问题标题】:error calling function ,[A call to PInvoke function unbalanced the stack]错误调用函数,[对 PInvoke 函数的调用使堆栈不平衡]
【发布时间】:2010-09-20 06:22:27
【问题描述】:

我有以下代码,一旦我运行我的应用程序,我就会得到这个错误

有人知道我如何解决这个错误吗?

错误:

对 PInvoke 函数“testcamera!EDSDKLib.EDSDK::EdsDownloadEvfImage”的调用导致堆栈不平衡。这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配

 IntPtr cameraDev;
            bool LVrunning = false;
            uint err = EDSDK.EDS_ERR_OK;
            uint device = 0;
            IntPtr MemStreamRef = new IntPtr(0);

            IntPtr EvfImageRef = new IntPtr(0);
            PictureBox pbLV;

            public LiveView(IntPtr c, PictureBox p)
            {
                cameraDev = c;
                pbLV = p;
            }

            internal void StartLiveView()
            {
                //LVrunning = true;
                //int i = 0;

                // Get the output device for the live view image
                err = EDSDK.EdsGetPropertyData(cameraDev, EDSDK.PropID_Evf_OutputDevice, 0, out device);
                Debug.WriteLineIf(err != EDSDK.EDS_ERR_OK, String.Format("Get Property Data failed: {0:X}", err));
                Debug.WriteLineIf(err == EDSDK.EDS_ERR_OK, String.Format("Liveview output is: {0:x}", device));

                Thread.Sleep(1000);

                // Set the computer as live view destination
                if (err == EDSDK.EDS_ERR_OK)
                {
                    err = EDSDK.EdsSetPropertyData(cameraDev, EDSDK.PropID_Evf_OutputDevice, 0,
                        Marshal.SizeOf(EDSDK.EvfOutputDevice_PC), EDSDK.EvfOutputDevice_PC);
                    Debug.WriteLine(String.Format("Liveview output to computer: {0:X}", err));
                }

                // Create a memory stream for the picture
                if (err == EDSDK.EDS_ERR_OK)
                {
                    err = EDSDK.EdsCreateMemoryStream(0, out MemStreamRef);
                    Debug.WriteLine(String.Format("Create Memory Stream: {0:X}", err));
                }

                // Get a reference to a EvfImage

                if (err == EDSDK.EDS_ERR_OK)
                {

**//i get error here**
                     **err = EDSDK.EdsCreateEvfImageRef(MemStreamRef, out EvfImageRef);** 

                    Debug.WriteLine(String.Format("Create Evf Imaage Ref: {0:X}", err));
                }

                Thread.Sleep(2000);
            }

【问题讨论】:

  • 请提供更多信息-dllimport,EdsDownloadEvfImage签名
  • 这是我的 dllimport,[DllImport("EDSDK.dll")] public extern static uint EdsCreateEvfImageRef(IntPtr inStreamRef, out IntPtr outEvfImageRef);
  • 什么是函数原生签名?

标签: c# .net pointers


【解决方案1】:

请对该函数使用 Cdecl 调用约定。不要问我为什么,它确实有效。

[DllImport("EDSDK.dll", CallingConvention=CallingConvention.Cdecl)]
public extern static uint EdsCreateEvfImageRef(IntPtr inStreamRef, out IntPtr outEvfImageRef);

[DllImport("EDSDK.dll",CallingConvention=CallingConvention.Cdecl)]
public extern static uint EdsDownloadEvfImage(IntPtr inCameraRef, IntPtr outEvfImageRef);   

【讨论】:

  • Cdecl:调用者清理堆栈。这允许使用可变参数调用函数,这使得它适合用于接受可变数量参数的方法。它使每个函数调用都包含堆栈清理代码。 msdn.microsoft.com/en-us/library/…
【解决方案2】:

在执行平台调用 (P/Invoke) 时,您必须告诉 CLR 参数是什么(这决定了它们如何编组)以及目标本地方法的调用约定是什么,以便运行时知道如何生成代码以正确推送参数并在调用后清理堆栈。如果签名不匹配,您最终会遇到类似于您所看到的运行时错误。

错误信息很好地解释了问题:

这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配

EDSDK.EdsCreateEvfImageRef 的 P/Invoke 签名与实现此功能的实际本机方法签名进行比较。

您可以通过在DllImport 属性上指定CallingConvention 属性来更改P/Invoke 的调用约定。 EDSDK.EdsCreateEvfImageRef 的调用约定很可能与您的其他 P/Invokes 的调用约定相匹配。

【讨论】:

  • 我把我的 dll 导入,[DllImport("EDSDK.dll")] public extern static uint EdsCreateEvfImageRef(IntPtr inStreamRef, out IntPtr outEvfImageRef);我的代码哪里错了?
  • 您的其他 P/Invokes 是什么样的? EdsDownloadEvfImage 的原生签名是什么样的?
  • 我不确定在哪里可以找到这个本机代码签名,我没有我的 dll 的来源。我只得到了 dll 本身
  • @user1400:在这种情况下,您需要一些文档来告诉您。如果这个 DLL 是某个 SDK 的一部分,我希望它会附带一个 .h 文件或内容的其他代码描述。如果 DLL 不是来自某些 SDK,那么您确定调用它导出的任何函数甚至是可能的(并且合法的)吗?
  • 它是 sdk 的一部分(佳能相机的 EDSDK 2.8),它有一些头文件
【解决方案3】:

我遇到了与发帖者相同的问题,结果我需要使用 EDSDK 库 (v2.10) 更改我的项目以使用 .NET 3.5 而不是 .NET 4.0。

【讨论】:

  • 我也遇到了类似的问题,通过将我的 .net 版本设置为 3.5 解决了
猜你喜欢
  • 1970-01-01
  • 2011-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-19
相关资源
最近更新 更多