Has anyone seen a working example of making an asynchronous callback from a C++ dll to VB6?
The steps are:
1. Set callback address by sending addressof subroutine to dll
2. dll stores this value in a global variable for later use
3. dll launches a seperate thread and returns control to VB
4. New thread performs some work and makes a callback to VB using the previously set address.
The problem is with the parameters passed back to VB
The logic works within the IDE
If compiled, the callback is made, but if I try to access the parameters passed, it crashes. This tells me there is something wrong with the stack?
Here is a demo code
C++
Code:/ All declarations which are needed resides in "windows.h" #include <windows.h> // Placeholder for function-export macros #define LIBRARY_EXPORT __declspec(dllexport) __stdcall // Function Declarations for Static Export extern "C" { long LIBRARY_EXPORT GetDBData(void); long LIBRARY_EXPORT SetCallbackProcAddr(long); } // Function Declaration for Callback function of the Calling App //typedef void (CALLBACK* TDataReadNotify)(long); typedef void (__stdcall *TDataReadNotify)(long); / Vars for Imported Functions TDataReadNotify DataReadNotify; HANDLE hThread; DWORD pThreadId; static DWORD DoTheWork(LPVOID lpParameter) { static long lDBData; // Doing stuff that takes 5 sec., i.e. reading DB Data. Sleep(5000); lDBData = 123; // Notify the caller app via CB-function. if (DataReadNotify != NULL) DataReadNotify(lDBData); return 0; }; long LIBRARY_EXPORT GetDBData(void) { long lProcAdr; // Get ProcAddress for Thread-Func and create/run the thread. lProcAdr = (long)(&DoTheWork); hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)lProcAdr, NULL, 0, &pThreadId); // Return to caller app. return 0; }; long LIBRARY_EXPORT SetCallbackProcAddr(long lProcAddress) { long Result = 0; // Set the Proc-Address for the notify-func of the caller app. DataReadNotify = (TDataReadNotify)lProcAddress; if (DataReadNotify == NULL) return 0; return 1; };
VB Code:
Option Explicit Private iWait As Long Private sDBData As String Private sMessage As String Public Declare Function GetDBData Lib "DLL_Callback.dll" Alias "_GetDBData@0" () As Long Public Declare Function SetCallbackProcAddr Lib "DLL_Callback.dll" Alias "_SetCallbackProcAddr@4" (ByVal lProcAddress As Long) As Long Sub Main() iWait = 1 ' Send Address-Pointer Information to the DLL Call SetCallbackProcAddr(AddressOf DataReadNotify) ' Call the function of the DLL, which reads DB-Info or something else. GetDBData ' if the DLL-function is still busy, loop until the DLL notifies via the CALLBACK-function "DataReadNotify()". Do While iWait = 1 DoEvents Loop iWait = iWait End Sub Public Sub DataReadNotify(ByVal lDBData As Long) MsgBox "Sample App: " & CStr(lDBData), vbOKOnly + vbInformation ' Set Wait to 0, so that WinMain can go further. iWait = 0 End Sub




Reply With Quote