VS2010に切り替えた後、マネージデバッグアシスタントは、C#アプリケーションからアンマネージC++関数を呼び出すと、アンバランススタックに関するエラーを表示します。
通常の容疑者は問題を引き起こしていないようです。他に確認する必要があるものはありますか? VS2008でビルドされたC++ dllおよびC#アプリケーションには問題がなく、奇妙なバグや神秘的なバグもありませんでした。
チェックされたものは次のとおりです。
C#:
[DllImport("Correct.dll", EntryPoint = "SuperSpecialOpenFileFunc", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true)]
public static extern short SuperSpecialOpenFileFunc(ref SuperSpecialStruct stuff);
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct SuperSpecialStruct
{
public int field1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string field2;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string field3;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string field4;
public ushort field5;
public ushort field6;
public ushort field7;
public short field8;
public short field9;
public uint field10;
public short field11;
};
C++:
short SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff);
struct SuperSpecialStruct
{
int field1;
char field2[256];
char field3[20];
char field4[10];
unsigned short field5;
unsigned short field6;
unsigned short field7;
short field8;
short field9;
unsigned int field10;
short field11;
};
エラーは次のとおりです。
マネージデバッグアシスタント「PInvokeStackImbalance」は「マネージアプリケーションパス」で問題を検出しました。
追加情報:PInvoke関数「SuperSpecialOpenFileFunc」の呼び出しにより、スタックのバランスが崩れました。これは、管理されたPInvoke署名が管理されていないターゲット署名と一致しないためです。 PInvoke署名の呼び出し規則とパラメーターが、ターゲットのアンマネージ署名と一致することを確認します。
デーンローズのコメント で述べたように、__stdcall
C++関数で、またはCallingConvention = CallingConvention.Cdecl
をDllImport
で。
C#ではなくstdcallを指定しますが、C++では指定しません。ここで不一致があると、関数と呼び出し側の両方がスタックから引数をポップします。
一方、デフォルトの呼び出し規則としてstdcallを有効にするコンパイラスイッチがあります(-Gz)それを使用していますか?
または、C++でこれを試してください
short __stdcall SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff);
構造体のC#宣言ではパディングを指定しませんが、C++バージョンでは指定しません。すべてが4の倍数ではなく、奇数の2バイトのshortではないchar配列を混合しているため、コンパイラはおそらく構造体内にパディングを挿入し、末尾を追加します。
#pragma pack
で構造体をラップして、パディングがないことを確認してください。
#pragma pack(Push)
#pragma pack(1)
// The struct
#pragma pack(pop)
説明と同じ問題がありました-何年も完璧に機能していたアンマネージC++アプリ。 VS2010にアップグレードすると、PInvokeStackUnbalancedメッセージの取得を開始しました。
上記のようにC++シグネチャに「__stdcall」を追加すると、問題はなくなりました。
次のように関数定義を更新します:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
うまくいきます。