调用到的PInvoke已经失衡堆栈......甚至与CDECL DLL导入失败 [英] A call to PInvoke has unbalanced the stack... dll import fails even with Cdecl
问题描述
啊哈,这个问题是全栈溢出,所以我已经着手增加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屋!