DLL_Callback: Sample for asyncronous inner-process operations.
Posted
by HarryF HarryF
on March 28th, 2002
Environment: VC6 SP3, VB6 SP3
This sample demonstrates the use of asyncronous inner-process operations.
In this case we have an app that wants to get data from a DB,
which could take a undefined long amount of time.
The app wants to do other work while waiting for the result of the DB-Call.
It calls the "GetDBData()"-function, which returns immediately.
After the DLL-function has done its work, it notifies the caller app
via the CALLBACK-function "DataReadNotify()".
A VB sample which uses this DLL with VB can be found in the "VB_Sample"-Path.
Library Source:
DLL_Callback.h
#ifndef _DLL_CALLBACK_ #define _DLL_CALLBACK_ // All declarations which are needed resides in "windows.h" #include <windows.h> // Placeholder for function-export macros #define LIBRARY_EXPORT __declspec(dllexport) __cdecl // 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 (* TDataReadNotify)(long); #endifDLL_Callback.cpp
// Comment out the line below, if you want STDCALL // for the VB-Example. #define CDECL_CALLING_CONVENTION #ifdef CDECL_CALLING_CONVENTION #include "DLL_Callback.h" #else #include "DLL_Callback_StdCall.h" #endif // Vars for Imported Functions TDataReadNotify DataReadNotify; HANDLE hThread; DWORD pThreadId; DWORD DoTheWork(LPVOID lpParameter) { 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) Result = 1; return Result; };
C++ Sample Source:
Callback_Sample.h
#ifndef _CALLBACK_SAMPLE_ #define _CALLBACK_SAMPLE_ // All declarations which are needed resides // in "windows.h" #include <windows.h> // Placeholder for function-import macros #define LIBRARY_IMPORT __declspec(dllimport) __cdecl // Function Declarations for Static // Import (aka "Implicied Linking") // This requires the Output-LIB of the DLL_Callback Library. extern "C" { int LIBRARY_IMPORT GetDBData(void); int LIBRARY_IMPORT SetCallbackProcAddr(long); } #endifCallback_Sample.cpp
#include "Callback_Sample.h"
int iWait = 1;
char sDBData[11];
char sMessage[64];
void DataReadNotify(long lDBData)
{
_ltoa(lDBData, sDBData, 10);
strcpy(sMessage, "DBData from DLL is: ");
strcat(sMessage, sDBData);
::MessageBox(0, sMessage,
"Sample App", MB_OK + MB_ICONINFORMATION);
// Set Wait to 0, so that WinMain can go further.
iWait = 0;
};
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
long lProcAdr;
// Get Address-Pointer of the CB-function
lProcAdr = (long)(&DataReadNotify);
// Send Address-Pointer Information to the DLL
SetCallbackProcAddr(lProcAdr);
// Call the function of the DLL, which reads DB-Info
// or something else.
GetDBData();
// Do other work while the DLL reads the DBData
// ...
// I.e.: Show a splash-screen, write values to an
// INI-File or whatever
// ...
// if the DLL-function is still busy, loop until
// the DLL notifies via the CALLBACK-function "DataReadNotify()".
while (iWait) {};
return 0;
};

Comments
helpful article
Posted by ricky_cpp on 12/10/2008 07:11amThanks..this article has helped in undestanding concept of callbacks in windows :-)
ReplyDLL_Callback: Sample for asyncronous inner-process operations.
Posted by Legacy on 10/21/2002 12:00amOriginally posted by: Suman Bhattacharya
This is working fine when running from VB IDE.But it fails after creating exe.It raises an error like "Unable to read from memory".I am doing a project which requires this sort of callback operation. This is an ergent requriement.Pls help me.
ReplyVB Crashing (Only code chg i was __stdcall) help!
Posted by Legacy on 08/08/2002 12:00amOriginally posted by: Mr Unlucky
It runs and returns the value and the message box appears with the value then Crash! vb completely crashes. Does anyone know why?
please help thanks.
Environment
ReplyVC6 No Service Pack / SP5
VB6 No Service Pack / SP5
callback
Posted by Legacy on 08/02/2002 12:00amOriginally posted by: St.Daniel
i realy dont get it
ReplyThread not need ..
Posted by Legacy on 03/30/2002 12:00amOriginally posted by: krkim
The Main Program is holding until the GetData() thread function routine to be end,
while (iWait) {}; cause this probelm..
so,thread routine is not meaning.
ReplyNot a good idea ...
Posted by Legacy on 03/28/2002 12:00amOriginally posted by: Robert Simpson
I highly recommend NOT using this method with VB.
The callback function is executed from a different thread than the thread that called GetDBData(), and no marshaling is done because this code runs in the absence of COM. VB is designed around COM, and VB's behavior will be erratic at best. Depending on what is done in the callback routine, your VB app may crash hard. Do NOT call any methods on any COM classes (in VB, all apps are COM classes, even the private ones), and take care not to do anything involving COM in the callback. It may work, but it breaks the fundamental rules of COM and is a huge no-no, especially if you want a stable, reliable application.
Also ... The DoTheWork() function is declared as:
DWORD DoTheWork(LPVOID lpParameter)
This is incorrect. It should be declared as:
DWORD WINAPI DoTheWork(LPVOID lpParameter)
ThreadProc()'s require the entry point to be _stdcall.
Robert Simpson
Programmer at Large
Black Castle Software, LLC
ReplyIt's useful,but...
Posted by Legacy on 06/05/2001 12:00amOriginally posted by: haopf
hi,
ReplyThis method is useful to me,but how can i pass a pointer
of buffer in vc++ to vb call back function? If i use a int*
pointer parameter,vb can't read data form it.
New bie!?
Posted by Legacy on 05/12/2001 12:00amOriginally posted by: Saad
Funny I don't see what the big deal is about this crap ?
ReplyGood Luck fella!
Welcome!
Posted by Legacy on 05/08/2001 12:00amOriginally posted by: Sergey
At least one Programmer finally realized the life is much easier without COM/COM+/DCOM/.NET
Reply