Announcement

Collapse
No announcement yet.

Byval/ByRef in DECLAREs

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

  • Byval/ByRef in DECLAREs

    When declaring functions in external DLLs (in this case the Win API) using the DECLARE statement, is it required that
    I spell out the parameter passing function or can I leave the parameter list 'generic' and use BYVAL/BYREF when I
    actually call the function? IOW, can my declare be:

    Declare SomeSub Lib "External.Dll" (Param1 as DWord, Param2 as Long, Param3 as SomeUDT)

    and then in code:

    SomeSub BYVAL Param1, BYREF Param2, BYREF Param3 ' UDTs can only be passed BYREF

    Granted, it's cleaner syntax to define the passing method in the DECLARE, but when debugging it's easier to just change
    the actual call.

    Sorry if this is covered in the docs, but I spent the afternoon trying to get a <expletive deleted> WinAPI function to
    work right, without much success. It's still bugging me, so I thought I'd post from home in the hope that
    I'll forget about it and not have any API nightmares.

    Thanks!



    ------------------
    Mark Newman
    Mark Newman

  • #2
    If you declare all parameters as BYREF (the default), then the compiled code will be constructed to expect to receive pointers to the actual data. Likewise, if you specify BYVAL, the actual values will be expected, not pointers to the values.

    When you pass parameters from the calling code with an *explicit* BYVAL, you effectively switch off type-checking by the compiler for that parameter.

    Now, if the called code expects a pointer (say, to a LONG), and you pass a BYVAL LONG from the calling code, the called code will receive an absolute LONG value, not an address of a LONG value. This will almost certainly earn you a GPF when the absolute LONG value tries to be used as a pointer address to a LONG.

    Essentially, declarations and sub/function prototypes are an important part of any program - they tell the compiler what sort of parameters the sub/function is going to be passed and how they should be passed. If you specify the wrong passing methods, you'll have to handle all of the type checking yourself (and get it right), which may add significant overhead to your development time.

    Therefore, if the compiler offers parameter type-checking, why not use it?

    May I suggest that you review the documentation that discusses BYVAL, BYREF and BYCOPY parameter passing - once you understand those methods, you'll understand how you can handle parameter passing.

    I hope this helps!


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

    Comment


    • #3
      Thanks Lance!

      I don't have PB installed at home so I can't look over the docs.
      I'm just trying to 'get my mind straight' and develop a plan of
      attack for Monday morning. Here it is Saturday afternoon & I'm
      still bugged by the problem, which violates my 'leave work at work'
      policy.

      First thing I'll check is my declares of the WinAPI functions to
      make sure I've got them right. They're mostly DWORDs and UDTs, but
      in some functions they're passed BYVAL, in others the function wants
      a pointer to them. I suspect I've got a few mixups.


      ------------------
      Mark Newman
      Mark Newman

      Comment


      • #4
        Mark, since many API function declarations exist in the WIN32API.INC and related .INC files, it makes sense to use those rather than rewrite them from scratch.

        I often see folks move code from VB to PB and then battle against the VB declarations. The VB declarations often need some translation due to the way VB handles passing strings BYVAL to DLL's, etc.

        In these cases, I usually suggest that the entire VB declaration section be dropped, and replaced with one line of code:
        Code:
        #INCLUDE "WIN32API.INC"
        I hope this helps!

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

        Comment


        • #5
          When you pass parameters from the calling code with an *explicit* BYVAL, you effectively switch off type-checking by the compiler for that parameter.
          That statement, exactly as written, should be in the documentation for the CALL verb. (and maybe in that for FUNCTION and SUB as well).

          MCM


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

          Comment


          • #6
            Lance,

            Oooh, how I wish that WIN32API.INC had these declares! I'm using functions in the SETUPAPI.DLL
            and HID.DLL (HID refers to "Human Interface Device", which could be a keyboard, mouse, joystick,
            gamepad, etc.) libraries to interface with some USB devices. The SETUPAPI.DLL functions are
            documented quite well in MSDN, but there's only the slightest mention of HID and no function
            documentation. I do have a Windows driver book that covers HID some, so I know what the functions
            are doing, but of course all the source is in C.

            It's especially frustrating since I've had a good amount of success with PB of late, recently
            completing a suite of 8 engineering test programs that helped us test & ship a new product on
            a very tight schedule. I actually enjoyed distributing the apps via email: "Just copy the attached
            exe and run it". No VB runtimes, no DLL Heck!

            But these dang C-porting projects are going to have me pushing up daisies before too long!

            Thanks!


            ------------------
            Mark Newman
            Mark Newman

            Comment


            • #7
              Hi All, I wonder which declare works faster and which saves more memory for BYVAL and BYREF ?

              Comment


              • #8
                Have you read Help for CALL Statement?

                Cheers,
                Dale

                Comment


                • #9
                  As you can see reasons for choosing aren't really speed or memory use. Although in the case of strings you "generally" don't want to use up stack space (which is memory) with BYVAL .

                  Cheers,
                  Dale

                  Comment


                  • #10
                    ANSWER #1:The relative performance, both speed and resource utilization, of BYVAL vs BYREF parameters depends on how often the receiving procedure uses either/both the value or the address of the parameter once passed.

                    ANSWER #2: If you are worried about this you are worrying about the wrong things.


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

                    Comment


                    • #11
                      Once again: "wonder" <> "worry"

                      Some people still have enquiring minds.
                      Last edited by Stuart McLachlan; 13 Apr 2021, 01:32 AM.

                      Comment


                      • #12
                        Tim,

                        Either will do, the difference is between a VALUE (1234) versus the ADDRESS of the value (12345678).

                        You can pass a value or an address BYVAL but if you are using the supplied prototypes (DECLAREs) they will require one or the other. BYREF is a convenience designed or the BASIC language, they both work and it would be very hard to find any difference as they both do the same thing. The only real pest is if you get a syntax error, you have to go ratting around in the include files to find the prototype to see if its speced as BYVAL or without it, BYREF.
                        hutch at movsd dot com
                        The MASM Forum

                        www.masm32.com

                        Comment


                        • #13
                          Originally posted by Tim Lakinir View Post
                          Hi All, I wonder which declare works faster and which saves more memory for BYVAL and BYREF ?
                          I can see very rare and specific circumstances where that is the reason to chose one over the other. However, that's not which these different qualifiers exist. If in doubt, you go with ByVal*), because this prevents you from accidentically changing the value of the passed variable. The calling code may rely on the unchanged value of the variable further down the line.

                          Only if you are 100% sure you absolutely need to change the value of the passed variable and that this change must be accessable by the calling code, you'd go with ByRef.

                          Here's what PB's help has to say (Sub/End Sub):
                          Originally posted by TFA
                          If you do not need to modify the parameters (true in many cases), you can speed up your calls by passing the parameters by value using the BYVAL keyword.
                          I'm not sure about the current versions of PB, but VB.NET finally made ByVal the default, if the qualifier is omitted. Traditionally - and I think that's till the case for PB, the default for BASIC is/was ByRef. Most likely to maintain beckwards compatibility with older BASIC versions which didn't distinguished at all and variables where ver onyl passed ByRef. But that's just my wild guess, I'm too lazy to research that now.

                          Comment


                          • #14
                            Originally posted by Knuth Konrad View Post
                            Here's what PB's help has to say (Sub/End Sub):

                            If you do not need to modify the parameters (true in many cases), you can speed up your calls by passing the parameters by value using the BYVAL keyword.
                            But note that under CALL it also says:
                            "Try to avoid passing large items BYVAL, as it's terribly inefficient, and there is a maximum size limit of 64 Kb for a given parameter list. Arrays cannot be passed BYVAL."


                            Comment


                            • #15
                              Thanks Everyone

                              noteworthy in post#2 , Lance said
                              If you declare all parameters as BYREF (the default), then the compiled code will be constructed to expect to receive pointers to the actual data. Likewise, if you specify BYVAL, the actual values will be expected, not pointers to the values.
                              BYREF is the default in PB while BYVAL is treated as inefficient under CALL help
                              I think the best is if we don't know much about the inner workings of some functions we should use BYCOPY which is a hybrid of BYREF and BYVAL
                              What do you say on this?

                              Comment


                              • #16
                                BYREF is the default in PB . . .
                                True.
                                . . . while BYVAL is treated as inefficient under CALL help
                                I don't see that.
                                I think the best is if we don't know much about the inner workings of some functions . . .
                                BYREF, BYVAL or BYCOPY are defined by when writing a procedure (SUB or FUNCTION). You don't know what is inside??? Or for calling someone else's procedure, you must account for which ever parameter passing method they defined.
                                . . . we should use BYCOPY which is a hybrid of BYREF and BYVAL
                                To use generally, would be least efficient.
                                Dale

                                Comment


                                • #17
                                  > BYVAL is treated as inefficient under CALL help

                                  Only if you use it to pass large items (reread the help file).

                                  If the size of the passed value is not greater that the size of a pointer, then passing parameters by value is faster because the data is accessed directly, instead of through a pointer.
                                  Last edited by José Roca; 13 Apr 2021, 03:24 PM.
                                  Forum: http://www.jose.it-berater.org/smfforum/index.php

                                  Comment


                                  • #18
                                    Thanks Dale and Jose, I have seen my senior developer in my company, passed large string arguments to the functions using GLOBAL variables
                                    rather than using BYREF or BYVAL , possibly he did this to bypass the pointer size limitations?

                                    Comment


                                    • #19
                                      What pointer size limitation????

                                      A pointer is 32 bits (in 32 bit OS or virtual OS). It can point to one byte or 2 Gig string.
                                      Dale

                                      Comment


                                      • #20
                                        think the best is if we don't know much about the inner workings of some functions we should use BYCOPY which is a hybrid of BYREF and BYVAL
                                        What do you say on this?
                                        You asked!

                                        What I say is, you need to learn what BYREF, BYVAL and BYCOPY mean and select the one which best suits your application. There is no "one size fits all silver bullet."



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

                                        Comment

                                        Working...
                                        X