错误调用函数,[调用PInvoke函数使堆栈不平衡]

时间:2010-09-20 06:22:28

标签: c# .net pointers

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

任何人都知道我如何修复此错误?

ERROR:

对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);
            }

3 个答案:

答案 0 :(得分:24)

请使用该函数的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);   

答案 1 :(得分:3)

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

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

  

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

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

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

答案 2 :(得分:2)

我遇到了与海报相同的问题,原来我需要使用EDSDK库(v2.10)更改我的项目以使用.NET 3.5而不是.NET 4.0。