1

アドイン アプリケーション A を VB.Net で、DLL B を C 言語で作成しています。アプリケーション A はコールバック メソッドを dll B に渡します。特定のイベントが発生すると、dll は A からコールバックを呼び出します。PC では全体が正常に動作しますが、ノートブックに移動するとエラーが発生します。

実行時チェックの失敗 #0 - ESP の値が関数呼び出しで適切に保存されませんでした。これは通常、ある呼び出し規約で宣言された関数を、別の呼び出し規約で宣言された関数ポインターで呼び出した結果です。

これは C コードの一部です。

typedef void (__cdecl * OFFICE_PTR)();
void  TAPIClient::tapiCallBack(
DWORD hDevice,
DWORD dwMessage,
DWORD dwInstance,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3){
switch (dwMessage)
{
    case LINE_CALLSTATE:
        switch (dwParam1)
        {
            case LINECALLSTATE_OFFERING:
                                    if(dwInstance!=NULL)
                {
                    try
                    {   
                        OFFICE_PTR vbFunc =(OFFICE_PTR)dwInstance;
                        vbFunc( );//Critical moment
                    }
                    catch(...)
                    {
                        MessageBox (NULL, L"( (OFFICE_PTR)dwInstance )(&sCallNr)",L"ERROR",MB_OK);
                    }
                }
            break;
        };
    break;
}

}

dwInstance はアプリケーションのアドレスです コールバック メソッド

これは VB.Net コードの一部です。

Public Class TapiPlugin

Public Delegate Sub P_Fun()

Private Declare Function startSpy _
    Lib "TAPIClient.dll" _
    (ByVal pFun As P_Fun) As IntPtr

Public Shared Sub simpleTest()
    MsgBox("Plugin sub simpleTest")
End Sub

Public Sub onStart()
    Dim pBSTR As IntPtr
    pBSTR = startSpy(AddressOf simpleTest)
    MsgBox(Marshal.PtrToStringAuto(pBSTR))
    Marshal.FreeBSTR(pBSTR)
End Sub

End Class

「vbFunc( )」を呼び出そうとすると、エラーが発生します。どんな助けにも感謝します。:D

4

3 に答える 3

1

呼び出し規約が の場合、次のcdeclようにデリゲートを宣言する必要があります。

<UnmanagedFunctionPointer(CallingConvention.Cdecl)>
Public Delegate Sub P_Fun()

これは .NET 2.0 以降でのみ行うことができます。これは、それ以前に属性が導入されていなかったためです (また、相互運用レイヤーはそれ以前にそれを認識するように変更されていませんでした)。

呼び出し規約が実際にstdcallある場合、デリゲートはそのままにしておくことができます。あなたはそうだと言いましたがstdcall、例外は呼び出し規約に不一致がある可能性があることを明示的に示しているため、疑問があります。

于 2009-01-10T23:44:01.523 に答える
0

2 台のコンピューターのポインターのサイズが異なる可能性がありますか? 1 台は 64 ビット マシンで、もう 1 台は 32 ビットしかないのでしょうか。

typedef void (__cdecl * OFFICE_PTR)();
void  TAPIClient::tapiCallBack(
DWORD hDevice,
DWORD dwMessage,
DWORD dwInstance,
...){
...
        OFFICE_PTR vbFunc =(OFFICE_PTR)dwInstance;
        vbFunc( );//Critical moment

DWORD 型は、ポインター型を渡すのに実際には有効ではありません。INT_PTR を使用する必要があります。

于 2008-12-19T09:43:56.933 に答える
0

コールバックを OFFICE_PTR 型のグローバル ポインタとして渡しましたが、同じ結果が得られました。PCでは、ノートブックで正常に動作し、クラッシュします:(

defが次のように見えると書いた間違いをお詫びする必要があります。

typedef void (__cdecl * OFFICE_PTR)();

しかし、実際には次のように見えます

typedef void (__stdcall * OFFICE_PTR)();
于 2008-12-19T09:56:56.330 に答える