运行时检查失败 #0 来自 C dll 的 vb.net 回调

发布于 2024-07-10 18:42:58 字数 1631 浏览 5 评论 0原文

我正在用 VB.Net 编写 Add-inn 应用程序 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

I'm writing Add-inn Application A in VB.Net and DLL B in C language.
Application A pass callback method to dll B.
When certain event occur the dll invoke the callback from A.
Whole works fine on my PC but when I move it to Notebook I get an error:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

This is part of C code:

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;
}

}

Where dwInstance is a address of application A callback method

This is part of VB.Net code:

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

The Error occur when I try call 'vbFunc( )'. I would be grateful for any help. :D

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

岁月无声 2024-07-17 18:42:58

如果调用约定是cdecl,那么您需要像这样声明您的委托:

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

您只能在.NET 2.0及之后的版本中执行此操作,因为在此之前没有引入该属性(并且互操作层是在此之前没有改变以承认这一点)。

如果调用约定确实是 st​​dcall,那么委托可以保持原样。 你说它是stdcall,但我有疑问,因为异常明确地告诉你调用约定可能不匹配。

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.

夏有森光若流苏 2024-07-17 18:42:58

两台计算机的指针大小可能不同吗? 也许一台是 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 。

Do the two computers have different pointer sizes perhaps? Maybe one is a 64 bit machine and the other only 32?

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

The DWORD type is not really valid for passing pointer types. You should be using INT_PTR I guess.

流云如水 2024-07-17 18:42:58

我认为这不是检查它的理由,我将回调作为 OFFICE_PTR 类型的全局指针传递,并且得到了相同的结果。 在 PC 上它工作正常,在笔记本上它崩溃了:(

必须为我写的 def 看起来像这样的错误道歉:

typedef void (__cdecl * OFFICE_PTR)();

但实际上它看起来像

typedef void (__stdcall * OFFICE_PTR)();

I thing it is not a reason to check it out I passed the callback as global pointer of type OFFICE_PTR and i get the same result. On PC it work fine on Notebook it crash :(

A have to apologies for a mistake I wrote that the def look like:

typedef void (__cdecl * OFFICE_PTR)();

but for real it looks like

typedef void (__stdcall * OFFICE_PTR)();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文