3

ネイティブ コードに対して .NET 4 への関数呼び出しを行うと、次の例外が発生します。

PInvoke 関数の呼び出しにより、スタックのバランスが崩れています。これは、マネージド PInvoke 署名がアンマネージド ターゲット シグネチャと一致しないことが原因である可能性があります。PInvoke シグネチャの呼び出し規約とパラメーターがターゲットのアンマネージド シグネチャと一致することを確認します。

ネイティブコードでの私の定義は次のとおりです。

typedef void ( CALLBACK* CB_DOWNLOADING )
(
      ULONG,    // secs elapsed
      LPARAM,   // custom callback param
      LPBOOL    // abort?
);


FETCH_API HttpFetchW
(
      LPCWSTR         url,
      IStream**       retval,
      LPCWSTR         usrname  = NULL,
      LPCWSTR         pwd      = NULL,
      BOOL            unzip    = TRUE,
      CB_DOWNLOADING  cb       = NULL,
      LPARAM          cb_param = 0,
      LPWSTR          ctype    = NULL,
      ULONG           ctypelen = 0
);

.NET に対応するものを次に示します。

[DllImport(dllPath, CharSet = CharSet.Unicode, SetLastError = true, CallingConvention =     CallingConvention.Cdecl)]
        internal static extern FETCH HttpFetchW
        (
            [MarshalAs(UnmanagedType.LPWStr)]
            string url,
            out System.Runtime.InteropServices.ComTypes.IStream retval,
            [MarshalAs(UnmanagedType.LPWStr)] 
            string usrname,
            [MarshalAs(UnmanagedType.LPWStr)] 
            string pwd,
            bool unzip,
            dlgDownloadingCB cb,
            IntPtr cb_param,
            [MarshalAs(UnmanagedType.LPWStr)] 
            string ctype,
            ulong ctypelen
        );

FETCH は列挙型です。

[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
    internal delegate void dlgDownloadingCB(ulong elapsedSec, IntPtr lParam, bool abort);


internal static void DownloadingCB(ulong elapsedSec, IntPtr lParam, bool abort)
        {
           // Console.WriteLine("elapsedSec = " + elapsedSec.ToString());
        }

.NET 4 内で代替案を提案できる人はいますか?

ご助力ありがとうございます。

4

2 に答える 2

4

HttpFetchW私が見ることができる唯一の明確なエラーは、C#ulongが 64 ビット幅であり、C++ULONGが 32 ビット幅であることです。最終パラメーターの C# コードはuint.

他に確認すべきことには、呼び出し規約が含まれます。よろしいですcdeclか?本当にそうあるSetLastErrorべきtrueですか?

コールバックに関しては、 で同じエラーを起こしますulong。そしてabortパラメータはLPBOOL. へのポインタBOOLです。したがって、C# パラメーターをパラメーターとして宣言する必要がありrefます。そして、コールバックはCALLBACKwhich isで宣言されますstdcall

したがって、デリゲートは次のようになります。

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
internal delegate void dlgDownloadingCB(
    uint elapsedSec, 
    IntPtr lParam, 
    ref bool abort
);

UnmanagedFunctionPointerまたは、デフォルトが であるため、単純に属性を削除しますstdcall

コールバックが であるため、関数もそうなる可能性が非常に高いと思いますstdcallFETCH_APIマクロが戻り列挙型と呼び出し規約の両方に展開されることを期待しています。あなたはそれらの詳細を提供しなかったので、私は推測することしかできません. 確認する必要があります。

他に確認できないことは、 ですCB_DOWNLOADING

とにかく、これらの仮定により、関数は次のようになります。

[DllImport(dllPath, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern FETCH HttpFetchW(
    string url,
    out System.Runtime.InteropServices.ComTypes.IStream retval,
    string usrname,
    string pwd,
    bool unzip,
    dlgDownloadingCB cb,
    IntPtr cb_param,
    string ctype,
    uint ctypelen
);
于 2013-09-29T20:37:41.977 に答える
0

出典:MSDN

.NET Framework バージョン 3.5 では、pInvokeStackImbalance MDA は既定で無効になっています。Visual Studio 2005 で .NET Framework バージョン 3.5 を使用すると、[例外] ダイアログ ボックス ([デバッグ] メニューの [例外] をクリックすると表示される) の [マネージ デバッグ アシスタント] リストに pInvokeStackImbalance MDA が表示されます。ただし、pInvokeStackImbalance の [Thrown] チェック ボックスをオンまたはオフにしても、MDA は有効または無効になりません。MDA がアクティブ化されたときに Visual Studio が例外をスローするかどうかのみを制御します。

https://msdn.microsoft.com/en-us/library/0htdy0k3(v=vs.110).aspx

于 2016-02-04T18:45:08.663 に答える