あはは、この質問はスタック オーバーフロー全体にあるため、既に 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 に変更しても (予想どおり)、同じエラーが発生します。
何かご意見は?構造体が何らかの形で干渉していると推測していますが、このようなインポートを使用することは私にとって一般的なタスクではないため、これは盲目的な推測です。グーグルに聞いて、ここでもっと深く調べてみましょう。
編集:これが役立つ場合、参照として渡される2つの構造体を次に示します:
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関連する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++ 関数に特に精通しているわけではありませんが、署名は問題ないようです。
編集ビンからビルドして実行するだけで、完全に正常に動作することがわかりました。Visual Studio を使用してデバッグ モードで実行しようとすると、この PInvoke エラーで失敗します。