Ошибка проверки времени выполнения # 0 vb.net обратный вызов из C dll - PullRequest
1 голос
/ 19 декабря 2008

Я пишу Приложение A для расширения в VB.Net и DLL B на языке C. Применение Метод обратного вызова для DLL B. Когда происходит определенное событие, DLL вызывает обратный вызов из A. Целая отлично работает на моем ПК, но когда я перехожу на ноутбук, я получаю сообщение об ошибке:

Ошибка проверки времени выполнения # 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

Ответы [ 3 ]

1 голос
/ 11 января 2009

Если соглашение о вызовах cdecl, вам нужно объявить своего делегата следующим образом:

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

Это можно сделать только в .NET 2.0 и после, так как атрибут не был введен до этого (и уровень взаимодействия не был изменен для его подтверждения до этого).

Если соглашение о вызовах действительно stdcall, то делегат может оставаться как есть. Вы сказали, что это stdcall, но у меня есть сомнения, поскольку исключение явно говорит вам, что может быть несоответствие в соглашениях о вызовах.

0 голосов
/ 19 декабря 2008

Я думаю, это не причина проверять это. Я передал обратный вызов как глобальный указатель типа OFFICE_PTR, и я получил тот же результат. На ПК нормально работает, на ноутбуке вылетает :(

Я должен извиниться за ошибку, которую я написал, что определение выглядит так:

typedef void (__cdecl * OFFICE_PTR)();

но на самом деле это выглядит как

typedef void (__stdcall * OFFICE_PTR)();
0 голосов
/ 19 декабря 2008

Возможно, два компьютера имеют разные размеры указателей? Может быть, один 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, я думаю.

...