1

我正在用 VB.Net 编写插件应用程序 A,用 C 语言编写 DLL B。应用程序 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

If the calling convention is cdecl, then you need to declare your delegate like this:

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

You can only do this in .NET 2.0 and after, as the attribute was not introduced before then (and the interop layer was not changed to acknowledge it before that).

If the calling convention is indeed stdcall then the delegate can remain as is. You said it is stdcall, but I have doubts, since the exception is explicitly telling you that there might be a mismatch in calling conventions.

于 2009-01-10T23:44:01.523 回答
0

两台计算机的指针大小可能不同吗?也许一台是 64 位机器而另一台只有 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 回答