Announcement

Collapse
No announcement yet.

DLL call function in owning EXE

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • DLL call function in owning EXE

    I have an EXE and DLL. When started the EXE calls some functions in the DLL, and the DLL then does some monitoring. (unrelated).
    What i need to do now, is when the DLL wants to raise an event - it needs to call a function or somehow return several LONGs and STRINGS to the main EXE.

    I'm unsure how to do this - whether to use SendMessage, or make the DLL somehow call a function in the main EXE.

    I thought of creating a function in the DLL that would allow the EXE to poll for events. But decided this would be too processor intensive.
    Another restricting factor is that my EXE needs to return a 1 or 0 back to the DLL after the DLL has raised the event.

    Any help would be appreciated.

    - Nathan

    [This message has been edited by Nathan Evans (edited August 07, 2001).]

  • #2
    I'd just send a windows message back to the .exe. This would be easy to process.

    Best Regards,
    Don

    ------------------
    dickinson.basicguru.com
    Don Dickinson
    www.greatwebdivide.com

    Comment


    • #3
      I'm using the following code to send a message back to the EXE. It should be setting a variable of lResult, to what the
      message pump was set to in the EXE. But it always returns 0

      Code:
            LOCAL hDlg AS LONG, lResult AS LONG
            hDlg = FindWindow("", "TestApp1")
            MSGBOX FORMAT$(hDlg) 'for debugging, just to make sure the window was found..
            DIALOG SEND hDlg, %WM_USER + 999&, 123123, 123123 TO lResult
            MSGBOX "result: " & FORMAT$(lResult) 'lResult always seems to return 0
      and in the EXE

      Code:
            CASE %WM_USER + 999& : MSGBOX FORMAT$(CBWPARAM): FUNCTION = 1
      The EXE receives the message fine, but the lResult stays at 0.


      What am i doing wrong?

      Thanks!

      - Nathan

      ------------------

      Comment


      • #4
        The callback return value is being cleared by the dialog engine. Essentially, the return value is "owned" by the dialog engine, rather than your own code.

        You could try to use CALL SetWindowLong(CBHNDL, %DWL_MSGRESULT, value&) in the callback.


        ------------------
        Lance
        PowerBASIC Support
        mailto:[email protected][email protected]</A>
        Lance
        mailto:[email protected]

        Comment


        • #5
          Lance,

          I tried the following:

          Code:
             CASE %WM_USER + 999& : MSGBOX FORMAT$(CBWPARAM): CALL SetWindowLong(CBHNDL, %DWL_MSGRESULT, 1)
          But the lResult still contained 0.



          - Nathan

          ------------------


          [This message has been edited by Nathan Evans (edited August 07, 2001).]

          Comment


          • #6
            Are you still setting FUNCTION = 1 in addition to SetWindowLong() ?


            ------------------
            Lance
            PowerBASIC Support
            mailto:[email protected][email protected]</A>
            Lance
            mailto:[email protected]

            Comment


            • #7

              Nathan, you could always send a message back to the dll from the exe
              too. This way you could send your result in lparam or wparam. Or you
              could call a function in the dll that would set a global varaible inside
              of the dll that could then be accessed by the dll process and cleared
              back to zero. Just a few work arounds to consider...


              Scott



              ------------------
              Scott Slater
              Summit Computer Networks, Inc.
              www.summitcn.com

              Comment


              • #8
                Lance,

                I recoded the EXE in Visual Basic, and its returning back fine now.

                I'm not really bothered, as i was going to code the EXE in VB anyway - but i was just testing the DLL
                with a PB EXE as it was quicker to get into subclassing than VB.

                Stay tuned though because i'll no doubt have some more probs'.

                Thanks for your help everyone!

                - Nathan

                ------------------

                Comment


                • #9
                  Can i use one of the DIALOG SEND parameters to send a Type structure over to my VB program?

                  Thanks!!

                  - Nathan

                  Comment


                  • #10
                    You'll probably have to send the address (varptr) of the structure over to vb as lparam or wparam. Then in vb, use RtlMoveMemory (or the like) to copy the data into your vb structure.
                    Best Regards,
                    Don

                    ------------------
                    dickinson.basicguru.com
                    Don Dickinson
                    www.greatwebdivide.com

                    Comment


                    • #11
                      > make the DLL somehow call a
                      > function in the main EXE.

                      All this talk about messages and dialogs sounds like "the hard way" to me.

                      If you wrote both the DLL and EXE, you should be able to simply DECLARE (in the source for the DLL) the function that is located in the EXE. Then you just call the function!.

                      If your application is single-theaded, it should be just this easy...

                      Code:
                      DECLARE FUNCTION MyFunc LIB "WHATEVER.EXE" ALIAS "MyFunc" (params) AS LONG
                      ...and make sure the function is marked FOR EXPORT in the EXE. (Of course VB doesn't do EXPORTs, but if the EXE is written in PB it should work perfectly.)

                      Or am I missing something?

                      -- Eric

                      ------------------
                      Perfect Sync Development Tools
                      Perfect Sync Web Site
                      Contact Us: mailto:[email protected][email protected]</A>



                      [This message has been edited by Eric Pearson (edited August 07, 2001).]
                      "Not my circus, not my monkeys."

                      Comment


                      • #12
                        Eric,

                        The EXE is coded in VB - so i can't use Exports

                        Don,

                        I've been working with CopyMemory all day trying to get this to work. But VB keeps returning incorrect
                        values from the Type structure. I'm working on it though

                        Thanks!!

                        ------------------

                        Comment


                        • #13
                          No matter what I do, the VB program GPFs as if i'm not allowed to read that memory.

                          My PBDLL fills wParam with the SIZEOF, and lParam with a VARPTR to the type structure.

                          Then in my VB program:

                          Code:
                                     Dim cntd As connectdata
                                     CopyMemory cntd, ByVal lParam, ByVal wParam
                          Any ideas?

                          Thanks.

                          Comment


                          • #14
                            When returning a pointer to a UDT (or to any variable for that matter) it cannot be a LOCAL variable in the DLL, or it's memory is freed when the Sub/Function terminates, and you'll get a GPF when you try to reference it via the pointer from outside of the module (or from another Sub/Function in the same module).

                            Use STATIC or GLOBAL scope in the DLL code instead...

                            ------------------
                            Lance
                            PowerBASIC Support
                            mailto:[email protected][email protected]</A>
                            Lance
                            mailto:[email protected]

                            Comment


                            • #15
                              Nathan --

                              > The EXE is coded in VB - so i can't use Exports

                              Sorry, I thought you converted the EXE from PB to VB to solve this problem, and that it was a pretty quick re-write (based on the dates/times of your messages) that wouldn't be hard to un-do.

                              You're right, VB can't create "real" EXEs and DLLs with exported functions, so you can't just cross-DECLARE the functions as you can with PB.

                              I suppose you could use the VB AddressOf operator (the rough equivalent of PB's CODEPTR function) to pass the address of the VB function to the DLL, during the EXE initialization. Then you could use CALL DWORD in the DLL to "call back" to the function in the EXE. That works perfectly with PB EXEs and DLLs, and it should work with VB... but I've never tried it with VB. According to the VB docs it should work.

                              -- Eric


                              ------------------
                              Perfect Sync Development Tools
                              Perfect Sync Web Site
                              Contact Us: mailto:[email protected][email protected]</A>
                              "Not my circus, not my monkeys."

                              Comment


                              • #16
                                Actually in VB is possible to use traditional technique.
                                Imagine that we wrote Pb.Dll, which has starting function
                                Code:
                                   Function Pb (VB_hWnd As Long) Export As Long
                                 ...   
                                   End Function
                                where VB_hWnd is a handle of main VB form.

                                In Form_Load we call two functions
                                1) Hook Me.hWnd <-- to subclass VB form
                                2) Pb Me.hWnd <-- to pass hWnd of main VB form to PB DLL

                                Pb/DLL program can send messages to VB window by usual way.

                                Now how Hook and subclass functions look (separate VB module).
                                Code:
                                Option Explicit
                                
                                Declare Function Pb Lib "Pb.Dll" Alias "PB" (hWnd As Long) As Long
                                
                                Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
                                   ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
                                
                                Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, _
                                   ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
                                
                                Public Const GWL_WNDPROC = -4
                                Public Const WM_DESTROY = &H2
                                Public Const WM_USER = &H400
                                Global lpPrevWndProc As Long
                                
                                Public Sub Hook(hWnd As Long)
                                   lpPrevWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
                                End Sub
                                
                                Function WindowProc(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
                                   Select Case wMsg
                                      Case WM_USER + xxx: <---- Process Pb Message
                                      Case WM_DESTROY: SetWindowLong hWnd, GWL_WNDPROC, lpPrevWndProc
                                   End Select
                                   WindowProc = CallWindowProc(lpPrevWndProc, hWnd, wMsg, wParam, lParam)
                                End Function
                                ------------------
                                E-MAIL: [email protected]

                                Comment


                                • #17
                                  Morning,

                                  I'm actually receiving the messages fine at the VB program - but having problems copying the data from the pointer and length
                                  into a VB type.

                                  Code:
                                         Dim cntd As sockaddr
                                         CopyMemory tempdata, ByVal lParam, ByVal 5
                                  I've tried sending a STRPTR of a String to the VB app with SendMessage - but it still GPFs.

                                  I also tried using CALL DWORD to an AddressOf a sub in my VB app - this caused the EXE to exit abruptly, no GPF however.

                                  Eric, this is just the start of the program and the EXE must be coded in VB, and DLLs in PB.

                                  This DLL is using SetWindowsHookEx within it's code - maybe this is causing the problems?

                                  Thanks!



                                  [This message has been edited by Nathan Evans (edited August 08, 2001).]

                                  Comment


                                  • #18
                                    I have *no idea* why this simple bit of code isn't working..

                                    In my PB DLL:

                                    Code:
                                          STATIC gtempdata AS STRING
                                          gtempdata = "test data"
                                    
                                          DIALOG SEND hDlg, %WM_USER + 999&, 0, VARPTR(gtempdata) TO lResult
                                    In my VB EXE's WindowProc function:

                                    Code:
                                          Case WM_USER + 999
                                                      
                                               Dim tempdata As String
                                                 tempdata = Space$(255)
                                                  CopyMemory tempdata, ByVal lParam, ByVal 1
                                                  MsgBox tempdata
                                                 WindowProc = 1
                                    The VB EXE is getting the Pointer to the string variable, then uses CopyMemory to grab just 1 byte from it. But it GPFs!



                                    [This message has been edited by Nathan Evans (edited August 08, 2001).]

                                    Comment


                                    • #19
                                      VARPTR on a dynamic string returns a pointer to the string handle. You probably want to pass the STRPTR value instead.

                                      Also, the most likely reason the VB code is able to return the function return value is that it is unlikely to be using the dialog engine (VB tends to use it's own custom windows). It is the Windows Dialog engine which is most likely to be swallowing your FUNCTION = values (PowerBASIC's DDT engine relies on the Windows dialog engine for default message handling).

                                      Semen shows you here how to use dialog subclassing to manipulate the message sucessfully.

                                      As someone else has asked... Do you have to use messaging here? calling DLL functions directly and passing strings as parameters seems the easiest solution.



                                      ------------------
                                      Lance
                                      PowerBASIC Support
                                      mailto:[email protected][email protected]</A>
                                      Lance
                                      mailto:[email protected]

                                      Comment


                                      • #20
                                        Lance,

                                        I have tried using STRPTR in place of VARPTR but makes no difference. I think it is my VB code at fault, rather than the PB code.

                                        I am 'calling back' my EXE, from a DLL - so i am using a VB WindowProc, the one Semen kindly posted.

                                        I have to use Messaging, since i have tried and not succeeded in using a callback to the VB EXE. Besides, my VB app is actually receiving the message, but
                                        is GPF'ing when attempting to read the variable at the pointer.

                                        I've been experimenting in using just simple Strings (let alone Types) to see what's up, and i could send a pointer to a 255 byte string across, then have VB attempt to read just 1 byte of it - but a GPF.



                                        - Nathan

                                        Comment

                                        Working...
                                        X