调用到的PInvoke已经失衡堆栈......甚至与CDECL DLL导入失败 [英] A call to PInvoke has unbalanced the stack... dll import fails even with Cdecl

查看:105
本文介绍了调用到的PInvoke已经失衡堆栈......甚至与CDECL DLL导入失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

啊哈,这个问题是全栈溢出,所以我已经着手增加CallingConvention = CallingConvention.Cdecl已经为我不得不导入其他库,但在这种情况下工作得很好,没有什么变化,仍然失败具有相同的错误消息。

Aha, this question is all over stack overflow so I've already proceeded to add CallingConvention = CallingConvention.Cdecl which has worked just fine for other libraries I've had to import but in this case, nothing changes and it still fails with the same error message.

原来的code这个就出来了一个.NET 3.5的项目和工作完全正常:

The original code for this came out of a .net 3.5 project and works perfectly fine:

[DllImport("Compiled DSP.dll")]
private static extern int fnGetConfigParam(int nID, ref stParamInt pstParam);

[DllImport("Compiled DSP.dll")]
private static extern int fnGetConfigParam(int nID, ref stParamFloat pstParam);

新项目是一个.NET 4.0的项目,试图调用同一个库。我已经添加了调用约定:

The new project is a .net 4.0 project that is trying to call the same library. I've already added the calling convention:

[DllImport("Compiled DSP.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int fnGetConfigParam(int nID, ref stParamInt pstParam);

[DllImport("Compiled DSP.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int fnGetConfigParam(int nID, ref stParamFloat pstParam);

这两个裁判类型是结构。当我尝试运行相同的code调用此函数为3.5的项目,我得到的PInvoke的错误,即使我改变调用STDCALL(如预期),我得到了同样的错误。

Both of the ref types are structs. When I try to run the same code that calls this function as the 3.5 project, I get the PInvoke error, even if I change the call to StdCall (as expected) I get the same error.

有什么想法?我猜测,该结构是某种干扰而使用进口这样是不是对我来说是常见的任务,所以这是一个盲目的猜测。时问谷歌和闲逛更深的位置。

Any thoughts? I'm guessing that the struct is somehow interfering but using imports like this is not a common task for me so this is a blind guess. Time to ask google and poke around deeper on here.

修改:如果这是很有用的,这里有两个结构传递作为参考:

EDIT : In case this is useful, here are the two structs passed as reference:

stParamInt:

stParamInt:

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private struct stParamInt           
    {
        public uint unID;
        public int nValue;
        public int nValueMin;
        public int nValueMax;
        public int nValueDef;
        public int nUnitsType;
        public int nUnits;

        public byte[] GetBytes()
        {
            byte[] result = new byte[0];
            List<byte> buf = new List<byte>();
            buf.AddRange(BitConverter.GetBytes(unID));
            buf.AddRange(BitConverter.GetBytes(nValue));
            buf.AddRange(BitConverter.GetBytes(nValueMin));
            buf.AddRange(BitConverter.GetBytes(nValueMax));
            buf.AddRange(BitConverter.GetBytes(nValueDef));
            buf.AddRange(BitConverter.GetBytes(nUnitsType));
            buf.AddRange(BitConverter.GetBytes(nUnits));
            result = buf.ToArray();
            return result;
        }

        public stParamInt(byte[] buf)
        {
            unID = BitConverter.ToUInt32(buf, 0);
            nValue = BitConverter.ToInt32(buf, 4);
            nValueMin = BitConverter.ToInt32(buf, 8);
            nValueMax = BitConverter.ToInt32(buf, 12);
            nValueDef = BitConverter.ToInt32(buf, 16);
            nUnitsType = BitConverter.ToInt32(buf, 20);
            nUnits = BitConverter.ToInt32(buf, 24);
        }
    };

stParamFloat:

stParamFloat:

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private struct stParamFloat                 
    {
        public uint unID;
        public float fValue;
        public float fValueMin;
        public float fValueMax;
        public float fValueDef;
        public int nUnitsType;
        public int nUnits;

        public byte[] GetBytes()
        {
            byte[] result = new byte[0];
            List<byte> buf = new List<byte>();
            buf.AddRange(BitConverter.GetBytes(unID));
            buf.AddRange(BitConverter.GetBytes(fValue));
            buf.AddRange(BitConverter.GetBytes(fValueMin));
            buf.AddRange(BitConverter.GetBytes(fValueMax));
            buf.AddRange(BitConverter.GetBytes(fValueDef));
            buf.AddRange(BitConverter.GetBytes(nUnitsType));
            buf.AddRange(BitConverter.GetBytes(nUnits));
            result = buf.ToArray();
            return result;
        }

        public stParamFloat(byte[] buf)
        {
            unID = BitConverter.ToUInt32(buf, 0);
            fValue = BitConverter.ToSingle(buf, 4);
            fValueMin = BitConverter.ToSingle(buf, 8);
            fValueMax = BitConverter.ToSingle(buf, 12);
            fValueDef = BitConverter.ToSingle(buf, 16);
            nUnitsType = BitConverter.ToInt32(buf, 20);
            nUnits = BitConverter.ToInt32(buf, 24);
        }

    };

修改我设法挖掘出相关的DLL中的签名,这是在C ++中的非托管code以下方法签名:

EDIT I managed to dig out the signature within the related dll, it's in C++ unmanaged code with the following method signature:

COMPILEDDSP_API int fnGetConfigParam(int nID, struct stPint *pstParam)
{
    return CONFIG_GetSetConfigParam(GET_PARAM, nID, pstParam, &g_stActiveCfg, sizeof(struct stActiveConfig)/sizeof(struct stPint), NULL);
}

不幸的是,我,我不是在标准的C ++函数特别是流畅的,但签名似乎都很正常。

Unfortunately for me I'm not especially fluent in standard C++ functions but the signature appears to be fine.

修改我发现,它的工作原理prefectly罚款,如果我只是建立,并从我的仓运行。如果我尝试在调试模式下通过Visual Studio运行时,出现此错误的PInvoke。

EDIT I found that it works prefectly fine if I just build and run it from my bin. If I try to run in debug mode through visual studio, it fails with this PInvoke error.

推荐答案

取这些答案的样子

  • <一个href="http://stackoverflow.com/questions/15051660/physical-disk-size-not-correct-ioctldiskgetdrivegeometry/15073586#15073586">Physical磁盘大小不正确(IoCtlDiskGetDriveGeometry)

<一个href="http://stackoverflow.com/questions/15197195/how-to-pass-structure-as-pointer-in-c-dll-from-c-sharp/15197411#15197411">How从C#传递结构指针在C DLL

How to pass structure as pointer in C dll from C#

您可以通过 REF 的IntPtr 结构,进口将

You can pass the ref structures with IntPtr, the importing would be

[DllImport("Compiled DSP.dll")]
private static extern int fnGetConfigParam(int nID, IntPtr pstParam);

和测试

var sizeParamInt=Marshal.SizeOf(typeof(stParamInt));
var marshalParamInt=Marshal.AllocHGlobal(sizeParamInt);
fnGetConfigParam(123, marshalParamInt);
var paramInt=(stParamInt)Marshal.PtrToStructure(marshalParamInt, typeof(stParamInt));
Marshal.FreeHGlobal(marshalParamInt);

请注意,我没有尝试的调用约定,您可能需要测试与实际code。

Note that I didn't try for the calling conventions, you might need to test with your actual code.

这篇关于调用到的PInvoke已经失衡堆栈......甚至与CDECL DLL导入失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆