Announcement

Collapse
No announcement yet.

Callbacks? DLL -> EXE

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

  • Callbacks? DLL -> EXE

    I am hoping someone can point me in the right direction.

    I have a PB created DLL that performs a time consuming task. I
    would like to be able to send messages back to the calling EXE
    so the EXE can process them if it needs to.

    For example, the DLL will calculate the completion percentage
    of the task (e.g. 80%) and pass that value back to the EXE. The
    EXE can then use that value to update a progress bar to display
    to the user. The EXE is also written in PB.

    Also, I would like to be able to do the same thing with the DLL
    calling a VB procedure so the VB app can display a progress bar.

    This DLL will be used by either PB or VB EXE's.

    Any help is appreciated!

    Thanks,




    ------------------
    Paul Squires
    mailto:[email protected][email protected]</A>
    Paul Squires
    FireFly Visual Designer (for PowerBASIC Windows 10+)
    Version 3 now available.
    http://www.planetsquires.com

  • #2
    I'm sure there are cleverer solutions, but a way I used once, was
    by sending messages to a TextBox in the VB exe. I simply put a value
    in a string, txt = format$(t) and then used
    SendMessage vbTxthWnd, %WM_SETTEXT, 0, STRPTR(txt)

    Then I placed code in VB's textbox Change_Event, that triggered some
    actions, like positioning a progressbar. Actually very fast, and easy
    to do. vbTxthWnd was sent from VB to the DLL via one of the parameters
    in the function call.


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

    Comment


    • #3
      paul --
      vb forms are ordinary windows, which possible to subclass.
      the easiest way (in my understanding) to send from pb to main vb form wm_user + xxx messages and to process them, using vb statements only.
      take a look http://www.powerbasic.com/support/pb...ad.php?t=22906
      here was used exactly this approach.

      [this message has been edited by semen matusovski (edited march 11, 2001).]

      Comment


      • #4
        Use AddressOf in VB
        The only risk you have is in exchanging data.
        Strings for example are in unicode unless you convert them to byte arrays

        Asynchroon operations like threads will crash when using a standard way.
        SendMessage and Postmessage will do instead.


        ------------------
        hellobasic

        Comment


        • #5
          Borje, Semen

          Those are really neat solutions. I would never have thought of
          it. They are nice also because the user can place a hidden
          textbox on the form where the progress bar will be.

          Edwin, I did some reading on the AddressOf function and I think
          (for my purposes) the biggest drawback is that the function
          being called in VB *must* be in a module. This would make the
          code on the VB end a little more sloppy because the callback
          code would be separated from the form code.

          Also, this DLL may be used by other languages (such as UltimADE)
          which I don't think has an equivalent to AddressOf.

          How about the DLL communicating with a PowerBasic EXE? Should I
          use the SendMessage solution from above or is there another
          standard way that most people use?

          Thanks



          ------------------
          Paul Squires
          mailto:[email protected][email protected]</A>
          Paul Squires
          FireFly Visual Designer (for PowerBASIC Windows 10+)
          Version 3 now available.
          http://www.planetsquires.com

          Comment


          • #6
            The DLL runs a task, this prevents using the application during this time unless you make use of threads.
            VB6 doesn't do threads very well. (read the FAQ on PB site for a solution)

            This also means a async. operation.

            Sendmessage is the easiest, call (VB)exe by using a hidden control.
            On message, a simple call to the DLL would be enough to get the right values from the DLL..
            WM_KEYDOWN should do fine.




            ------------------
            hellobasic

            Comment


            • #7
              Paul --
              VB is not able to create true DLL.
              Otherwise it was not necessary to create special programs http://moreinfo.vbonline.com/vbonlin...ll/default.htm

              From another side, PB has not native support of COM objects.
              Of course, using third-party DLL, this question is also possible to solve.

              But, honestly, words "VB DLL" (which requires a lot of run-time dll/ocx), at least for me sounds terrible.

              ------------------
              E-MAIL: [email protected]

              Comment


              • #8
                Edwin,

                You're right. I have read many posts from the Forum's archives
                and it seems that using AddressOf has many problems especially
                if strings are involved.

                I will stick to using the SendMessage solution - it is simple
                and easy to implement for me. Thanks,

                Semen, I did not understand your last post. The DLL I created
                was in PB *not* VB.



                ------------------
                Paul Squires
                mailto:[email protected][email protected]</A>
                Paul Squires
                FireFly Visual Designer (for PowerBASIC Windows 10+)
                Version 3 now available.
                http://www.planetsquires.com

                Comment


                • #9
                  Sorry, I thought that you raised a new question.
                  VB calls PB - here all is enough simple and tested.
                  But sometimes appears a wish to call VB ActiveX DLL from PB to work with COM objects.
                  I think I'm under impression of http://lockfree.50megs.com/linker.html
                  (unf. it doesn't work correctly, but maybe ...)

                  ------------------
                  E-MAIL: [email protected]

                  Comment


                  • #10
                    Paul,

                    I stay ignorant of VB on purpose but to get a DLL to send information
                    back to its calling exe is usually done with by writing a callback
                    function.

                    What you pass to the DLL among other parameters is the address of a
                    function that you write in the EXE. This is done with CodePtr(YourFunc).

                    In the DLL, when you need to pass info back to the calling EXE, you can
                    either use the CALL DWORD notation in PowerBASIC or call the address
                    directly in inline assembler with the standard PUSH/CALL syntax.

                    The parameters you pass to the callback function in your EXE must match
                    what you pass to it from the DLL making the direct call to the address.

                    If you need the EXE to remain accessible while the DLL is running, put
                    the DLL call in a seperate thread.

                    It may sound a bit messy but its no big deal to do and its a very useful
                    capacity.

                    Regards,

                    [email protected]

                    ------------------
                    hutch at movsd dot com
                    The MASM Forum

                    www.masm32.com

                    Comment


                    • #11
                      I would tend to think that if you had a variable (Lets say g_Percentcomplete) in your DLL and you wanted to send it back to the EXe you might do this:


                      In the EXE keep checking one function

                      The function in the DLL would be like this:


                      Function SendProgress(wPercent) EXPORT as long
                      Function = wPercent
                      End function

                      You would probably need to do it in a new thread of course, so that it can open that path of communication instead of being "Hung" waiting for the DLL to complete...

                      The progress bar is a neat idea, it could make that call and the function could actually be something like this:


                      Function PercentCOmplete() EXPORT AS LONG
                      Function = g_PercentComplete
                      End function


                      This way the DLL would always be updating that global variable, and it would always be fresh for that function.
                      And it would not require interrupting the DLL.


                      Scott

                      ------------------
                      Scott
                      Scott Turchin
                      MCSE, MCP+I
                      http://www.tngbbs.com
                      ----------------------
                      True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                      Comment


                      • #12
                        Scott,

                        Unfortunately I don't think this suggestion will work given my
                        situation.

                        The DLL is performing a reindex of a database. The EXE calls
                        a function (e.g. DB_REINDEX) in the DLL and waits for the DLL
                        to do its magic. The DLL must send the message back to the EXE
                        as it progresses through the reindex.

                        I know ZERO about implementing threads (I'm only now fully
                        understanding pointers!), so maybe your solution is to call the
                        Reindex and have a different thread call the DLL routine to
                        get the percentage complete while the original thread waits for
                        the reindex to complete? If so, I guess this would work for my
                        PB users, but for VB - well, need I say more....

                        Thanks,




                        ------------------
                        Paul Squires
                        mailto:[email protected][email protected]</A>
                        Paul Squires
                        FireFly Visual Designer (for PowerBASIC Windows 10+)
                        Version 3 now available.
                        http://www.planetsquires.com

                        Comment


                        • #13
                          Can't help you with the VB interface part, but what I do in my PB exe's which call PB DLLs is to pass the windowhandle of the progress bar as a parameter to the DLL; in the DLL I check if this value is set and use SendMessage when applicable, as in...

                          [code]
                          $COMPILE EXE

                          TYPE DllParmType
                          HwndProgress AS LONG
                          OtherParm as LONG
                          END TYPE

                          ....
                          DECLARE FUNCTION Foo ALIAS "Foo" LIB "Foo.dll" (P AS DLLParmTYpe) AS LONG

                          ...
                          DIM P AS DllParmType

                          P.HwndProgress = CreateWindow (yadda, yadda)
                          P.OtherParm = whatever

                          Stat = Foo(P)

                          ....

                          $COMPILE DLL
                          TYPE DllParmType
                          HwndProgress AS LONG
                          OtherParm as LONG
                          END TYPE

                          FUNCTION Foo (P AS DllParmType) EXPORT AS LONG

                          yadda, yadda..

                          DO
                          IF ISTRUE(P.hWndProgress) THEN
                          PercentDone = howfar/total
                          (convert to appropriate value for stepit message if needed)
                          SendMessage P.hWndProgress %PBM_STEPIT, 0,0
                          END IF
                          (More processing)
                          LOOP
                          END FUNCTION
                          [code]

                          This lets me use the same DLL with PB/CC or PB/DLL simply by setting the hWndProgress member to either a valid value or zero.

                          You can do the same thing with DDT by using a UsingDDT member and setting that to true, then in the DLL, IF P.UsingDDT THEN DIALOG DOEVENTS

                          Just a thought...

                          MCM


                          Michael Mattias
                          Tal Systems Inc. (retired)
                          Racine WI USA
                          [email protected]
                          http://www.talsystems.com

                          Comment


                          • #14
                            Paul,

                            What I pasted in below is the basic mechanics of writing your own callback
                            routine. It has this logic, a DLL can make calls within the entire address
                            space of an executable file if it knows the address to call. This is done
                            by passing that address to it in the original call to the DLL.

                            The DLL test code
                            Code:
                              DECLARE FUNCTION AppCallBack(ByVal var as LONG) as LONG
                              
                              ' #########################################################################
                              
                              FUNCTION TestFunc ALIAS "TestFunc"(ByVal lpFunc as DWORD PTR) EXPORT as LONG
                              
                                  cntr& = 10000
                              
                                  ! neg cntr& ; invert sign
                              
                                  lbl1:
                              
                              call DWORD lpFunc USING AppCallBack(cntr&) TO x&
                                  ! inc cntr&
                                  ! js lbl1   ; jump if sign
                              
                                  call DWORD lpFunc USING AppCallBack(cntr&) TO x&
                              
                                  FUNCTION = 0
                              
                              END FUNCTION
                              
                              ' #########################################################################
                            Next is the code that you write in the EXE file which is the callback
                            function,
                            Code:
                            '##########################################################################
                              
                              FUNCTION MyCallBack(ByVal var as LONG) EXPORT as LONG
                              
                                  ! neg var
                              
                                  SetWindowText hWnd, ByCopy str$(var)
                              
                                  FUNCTION = 0
                              
                              END FUNCTION
                              
                            '##########################################################################
                            This just sets the text in the title bar to know that something has happened.
                            Following is the code to call the DLL, this is placed in a thread so that the
                            DLL executes asyncronously and does not lock up the calling app.
                            Code:
                                      Case  50
                                        hThread& = 0
                                        handl& = CreateThread(ByVal %NULL,_
                                                              0,_
                                                              CodePtr(CallFunc),_   ' address of thread
                                                              ByVal %NULL,_         ' passed value if needed
                                                              0,_
                                                              VarPtr(hThread&))
                                        CloseHandle handl&
                            Lastly is the function called by the thread,
                            Code:
                            '##########################################################################
                              
                              FUNCTION CallFunc(ByVal var as LONG) as LONG
                              
                                  TestFunc CodePtr(MyCallBack)
                              
                                  FUNCTION = 0
                              
                              END FUNCTION
                              
                            '##########################################################################
                            This function called by the thread itself calls the DLL function and passes
                            the address of the callback function in the EXE to the DLL.

                            Regards,

                            [email protected]

                            [This message has been edited by Steve Hutchesson (edited March 13, 2001).]
                            hutch at movsd dot com
                            The MASM Forum

                            www.masm32.com

                            Comment

                            Working...
                            X