啊哈,这个问题完全是堆栈溢出,所以我已经开始添加 CallingConvention = CallingConvention.Cdecl 这对于我必须导入的其他库来说效果很好,但在这种情况下,没有任何变化,它仍然失败同样错误信息。
原始代码来自 .net 3.5 项目,并且运行良好:
[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 项目,它试图调用同一个库。我已经添加了调用约定:
[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);
两种 ref 类型都是结构。当我尝试运行与 3.5 项目调用此函数的相同代码时,我收到 PInvoke 错误,即使我将调用更改为 StdCall(如预期的那样)我也会收到相同的错误。
有什么想法吗?我猜这个结构会以某种方式干扰,但使用这样的导入对我来说不是一项常见的任务,所以这是一个盲目的猜测。是时候询问谷歌并深入了解这里了。
编辑:如果这很有用,这里是作为参考传递的两个结构:
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:
[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++ 非托管代码中,具有以下方法签名:
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++ 函数并不是特别流利,但签名似乎很好。
编辑我发现如果我只是从我的 bin 构建并运行它,它就可以很好地工作。如果我尝试通过 Visual Studio 在调试模式下运行,则会失败并出现此 PInvoke 错误。