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.
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);
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);
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:
[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);
}
};
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);
}
Unfortunately for me I'm not especially fluent in standard C++ functions but the signature appears to be fine.
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.