CObject (CView - CDoument) callbacks
-
callback (p1, p2, p3, ....) { CView *pView = (CView *)p1 pView->whatever() causes ASSERT as defined in wincore.cpp - void CWnd::AssertValid() } MainApp{ CDocument::OnCommand - selected some operation from menu CView *pView = get active view call DLL (pView, p2, p3, ...) } DLL { put up dialog move slider, now need to update pView in main app callback(pView, p2, p3 ...) } No matter if I pass a ptr to CDocument or CView the callback will fail (ASSERT) someplace If I pass in the HWND and in the callback use CWnd::FromHandle() and then call InvalidateRect() I can get thinks to redraw but I want to access items in the Doc or View. The ASSERT code states // Note: if either of the above asserts fire and you are // writing a multithreaded application, it is likely that // you have passed a C++ object from one thread to another // and have used that object in a way that was not intended. // (only simple inline wrapper functions should be used) // // In general, CWnd objects should be passed by HWND from // one thread to another. The receiving thread can wrap // the HWND with a CWnd object by using CWnd::FromHandle. // // It is dangerous to pass C++ objects from one thread to // another, unless the objects are designed to be used in // such a manner. So does anyone have a way around this? Thanks in advance
Tony Teveris Gerber Scientific Products Senior Software Engineer Phone: 860 648 8151 Fax: 860 648 8214 83 Gerber Road West South Windsor, CT 06074
-
callback (p1, p2, p3, ....) { CView *pView = (CView *)p1 pView->whatever() causes ASSERT as defined in wincore.cpp - void CWnd::AssertValid() } MainApp{ CDocument::OnCommand - selected some operation from menu CView *pView = get active view call DLL (pView, p2, p3, ...) } DLL { put up dialog move slider, now need to update pView in main app callback(pView, p2, p3 ...) } No matter if I pass a ptr to CDocument or CView the callback will fail (ASSERT) someplace If I pass in the HWND and in the callback use CWnd::FromHandle() and then call InvalidateRect() I can get thinks to redraw but I want to access items in the Doc or View. The ASSERT code states // Note: if either of the above asserts fire and you are // writing a multithreaded application, it is likely that // you have passed a C++ object from one thread to another // and have used that object in a way that was not intended. // (only simple inline wrapper functions should be used) // // In general, CWnd objects should be passed by HWND from // one thread to another. The receiving thread can wrap // the HWND with a CWnd object by using CWnd::FromHandle. // // It is dangerous to pass C++ objects from one thread to // another, unless the objects are designed to be used in // such a manner. So does anyone have a way around this? Thanks in advance
Tony Teveris Gerber Scientific Products Senior Software Engineer Phone: 860 648 8151 Fax: 860 648 8214 83 Gerber Road West South Windsor, CT 06074
-
callback (p1, p2, p3, ....) { CView *pView = (CView *)p1 pView->whatever() causes ASSERT as defined in wincore.cpp - void CWnd::AssertValid() } MainApp{ CDocument::OnCommand - selected some operation from menu CView *pView = get active view call DLL (pView, p2, p3, ...) } DLL { put up dialog move slider, now need to update pView in main app callback(pView, p2, p3 ...) } No matter if I pass a ptr to CDocument or CView the callback will fail (ASSERT) someplace If I pass in the HWND and in the callback use CWnd::FromHandle() and then call InvalidateRect() I can get thinks to redraw but I want to access items in the Doc or View. The ASSERT code states // Note: if either of the above asserts fire and you are // writing a multithreaded application, it is likely that // you have passed a C++ object from one thread to another // and have used that object in a way that was not intended. // (only simple inline wrapper functions should be used) // // In general, CWnd objects should be passed by HWND from // one thread to another. The receiving thread can wrap // the HWND with a CWnd object by using CWnd::FromHandle. // // It is dangerous to pass C++ objects from one thread to // another, unless the objects are designed to be used in // such a manner. So does anyone have a way around this? Thanks in advance
Tony Teveris Gerber Scientific Products Senior Software Engineer Phone: 860 648 8151 Fax: 860 648 8214 83 Gerber Road West South Windsor, CT 06074
I don't see anything in your sample code that shows different threads. Am I missing something? Calls across the EXE/DLL boundary should be safe, unless the DLL is linked to a separate MFC library, in which case all bets are off. The only way this will work is to use a true MFC extension DLL[^]. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
I don't see anything in your sample code that shows different threads. Am I missing something? Calls across the EXE/DLL boundary should be safe, unless the DLL is linked to a separate MFC library, in which case all bets are off. The only way this will work is to use a true MFC extension DLL[^]. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
If the DLL is displaying a dialog and the dialog code through it's messageing calls the callback is there a problem. Do dialogs operate in the same thread or different ? When I first did this I thought that same as you but it does fail. In the DLL I am using some 3rd part imaging software (LEAD) but it all links with the same liraries.
Tony Teveris Gerber Scientific Products Senior Software Engineer Phone: 860 648 8151 Fax: 860 648 8214 83 Gerber Road West South Windsor, CT 06074
-
If the DLL is displaying a dialog and the dialog code through it's messageing calls the callback is there a problem. Do dialogs operate in the same thread or different ? When I first did this I thought that same as you but it does fail. In the DLL I am using some 3rd part imaging software (LEAD) but it all links with the same liraries.
Tony Teveris Gerber Scientific Products Senior Software Engineer Phone: 860 648 8151 Fax: 860 648 8214 83 Gerber Road West South Windsor, CT 06074
Unless you've left out some code, it's all on one thread. As shown, there's only one message loop - running in the EXE's CWinApp object. How is the dialog created in the DLL? Does the dialog use a different thread for it's message loop? Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
Unless you've left out some code, it's all on one thread. As shown, there's only one message loop - running in the EXE's CWinApp object. How is the dialog created in the DLL? Does the dialog use a different thread for it's message loop? Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
the DLL function AFX_MANAGE_STATE(AfxGetStaticModuleState( )); nRet = DoDialogBoxParam(IDD_BCI_DLG, hParentWnd, (DLGPROC)BCIDlgProc, (LPARAM) pBciDlgData); the partent windows is that of the main app, the dialog resource is in the DLL
Tony Teveris Gerber Scientific Products Senior Software Engineer Phone: 860 648 8151 Fax: 860 648 8214 83 Gerber Road West South Windsor, CT 06074
-
the DLL function AFX_MANAGE_STATE(AfxGetStaticModuleState( )); nRet = DoDialogBoxParam(IDD_BCI_DLG, hParentWnd, (DLGPROC)BCIDlgProc, (LPARAM) pBciDlgData); the partent windows is that of the main app, the dialog resource is in the DLL
Tony Teveris Gerber Scientific Products Senior Software Engineer Phone: 860 648 8151 Fax: 860 648 8214 83 Gerber Road West South Windsor, CT 06074
DoDialogBoxParam? I meant at the MFC/Win32 level - I have no idea what your functions do :) Is the dialog created using MFC or Win32? Modal or modeless? Also important is what type of DLL you're using - MFC extension DLL or regular DLL linked to MFC (see Kinds of DLLs[^]). Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
DoDialogBoxParam? I meant at the MFC/Win32 level - I have no idea what your functions do :) Is the dialog created using MFC or Win32? Modal or modeless? Also important is what type of DLL you're using - MFC extension DLL or regular DLL linked to MFC (see Kinds of DLLs[^]). Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
Sorry about that DLGPROC pfn; pfn = (DLGPROC) MakeProcInstance((FARPROC) pfnDialog, AfxGetApp()->m_hInstance); nRet = (L_INT) DialogBoxParam(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(nDialog), hWnd, pfn, lParam); FreeProcInstance((FARPROC) pfn); Regular DLL using / linked with MFC (NOT static, same as main app) within wincore.cpp here is where it fails // should be a normal window ASSERT(::IsWindow(m_hWnd)); // should also be in the permanent or temporary handle map CHandleMap* pMap = afxMapHWND(); ASSERT(pMap != NULL); I have to ask the programmer of the main app some questions. I agree with you so far so I think there has to be something in our code messing something up.
Tony Teveris Gerber Scientific Products Senior Software Engineer Phone: 860 648 8151 Fax: 860 648 8214 83 Gerber Road West South Windsor, CT 06074
-
Sorry about that DLGPROC pfn; pfn = (DLGPROC) MakeProcInstance((FARPROC) pfnDialog, AfxGetApp()->m_hInstance); nRet = (L_INT) DialogBoxParam(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(nDialog), hWnd, pfn, lParam); FreeProcInstance((FARPROC) pfn); Regular DLL using / linked with MFC (NOT static, same as main app) within wincore.cpp here is where it fails // should be a normal window ASSERT(::IsWindow(m_hWnd)); // should also be in the permanent or temporary handle map CHandleMap* pMap = afxMapHWND(); ASSERT(pMap != NULL); I have to ask the programmer of the main app some questions. I agree with you so far so I think there has to be something in our code messing something up.
Tony Teveris Gerber Scientific Products Senior Software Engineer Phone: 860 648 8151 Fax: 860 648 8214 83 Gerber Road West South Windsor, CT 06074
Tony Teveris wrote:
I have to ask the programmer of the main app some questions.
Yes :) The module state stuff can affect CWnd pointers across the EXE/DLL module boundary depending on the type of DLL. This needs to be managed correctly. The CHandleMap is related to the module state. Your CView is in the EXE's map but in the DLL function, you've changed the module state, so when the callback is called, the code on the EXE side isn't finding the CView object in the DLL's map. That's why the type of DLL is important. With a properly initialized extension DLL, you don't need to use the AFX_MANAGE_STATE macro. Using an MFC extension DLL is definitely the best/easiest for passing CWnds back and forth across the EXE/DLL boundary. The drawback to an extension DLL is it can't be used by a non-MFC EXE. If you must use a standard DLL, then you'll need to manage the module state for your callback. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
Tony Teveris wrote:
I have to ask the programmer of the main app some questions.
Yes :) The module state stuff can affect CWnd pointers across the EXE/DLL module boundary depending on the type of DLL. This needs to be managed correctly. The CHandleMap is related to the module state. Your CView is in the EXE's map but in the DLL function, you've changed the module state, so when the callback is called, the code on the EXE side isn't finding the CView object in the DLL's map. That's why the type of DLL is important. With a properly initialized extension DLL, you don't need to use the AFX_MANAGE_STATE macro. Using an MFC extension DLL is definitely the best/easiest for passing CWnds back and forth across the EXE/DLL boundary. The drawback to an extension DLL is it can't be used by a non-MFC EXE. If you must use a standard DLL, then you'll need to manage the module state for your callback. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
It is NOT an extension DLL, just a normal DLL. I see your point and will look into extension DLL or mangage the state in the callback. I think were done here - many thanks
Tony Teveris Gerber Scientific Products Senior Software Engineer Phone: 860 648 8151 Fax: 860 648 8214 83 Gerber Road West South Windsor, CT 06074
-
It is NOT an extension DLL, just a normal DLL. I see your point and will look into extension DLL or mangage the state in the callback. I think were done here - many thanks
Tony Teveris Gerber Scientific Products Senior Software Engineer Phone: 860 648 8151 Fax: 860 648 8214 83 Gerber Road West South Windsor, CT 06074
Tony Teveris wrote:
It is NOT an extension DLL, just a normal DLL
Cool. Try adding this to the top of the callback... AFX_MANAGE_STATE(AfxGetAppModuleState()); Mark
Mark Salsbery Microsoft MVP - Visual C++ :java: