Announcement

Collapse
No announcement yet.

Callbacks? DLL -> EXE

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

  • Steve Hutchesson
    replied
    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).]

    Leave a comment:


  • Michael Mattias
    replied
    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


    Leave a comment:


  • Paul Squires
    replied
    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>

    Leave a comment:


  • Scott Turchin
    replied
    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

    Leave a comment:


  • Steve Hutchesson
    replied
    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]

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

    Leave a comment:


  • Semen Matusovski
    replied
    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]

    Leave a comment:


  • Paul Squires
    replied
    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>

    Leave a comment:


  • Semen Matusovski
    replied
    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]

    Leave a comment:


  • Edwin Knoppert
    replied
    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.




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

    Leave a comment:


  • Paul Squires
    replied
    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>

    Leave a comment:


  • Edwin Knoppert
    replied
    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.


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

    Leave a comment:


  • Semen Matusovski
    replied
    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).]

    Leave a comment:


  • Borje Hagsten
    replied
    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.


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

    Leave a comment:


  • Paul Squires
    started a topic Callbacks? DLL -> EXE

    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>
Working...
X