No announcement yet.

PB dll: function parameters BYREF or BYVAL ?

  • Filter
  • Time
  • Show
Clear All
new posts

    PB dll: function parameters BYREF or BYVAL ?

    Hi all,

    I am developing a dll in PowerBasic, that is intended to be used by PB apps (of course), but also by every thinkable programming language that can call a 32 bits dll.

    Most of the functions parameters, exported by that dll, are LONG variables, some are dynamic strings.
    This is simular to my HIME.dll where most of the function input parameters are LONG variables, passed BYREF.

    If new customers of mine (non PB programmers) need support getting started with HIME, most of the time it is because they are 'struggling' with the fact that the function parameters are passed BYREF.
    The design decision to pass the parameters byref was made years ago and I even can't remember exactly why I chose it. Possibly because it was the PB default way and it seemed more efficient to me.

    But with this new dll I am working on, I can make that decision again: BYREF or BYVAL. It seems that, for most other programming languages other than PB, passing function parameters BYVAL seems 'easier' to do. Or atleast, those programmers seem more comfortable with it than with passing parameters byref.
    When calling such a dll from PB it hardly makes a difference at all so let's keep that aside.

    Do you have an opinion about this ? Either as a PB programmer writing dll's to be used by other programming languages or either as a programmer that (occasionally) programs in other languages besides PB.
    What would you prefer ? BYREF or BYVAL .

    Kind regards
    I don't care

    BYREF is basically the same thing as:

    BYVAL VARPR(Somevar)

    You can use BYVAL and the value passed is a pointer to the data.

    This is quite common in the Windows API, where the parameter is byval but its description is a pointer (API docs use the lp prefix for such variables).

    PB makes things easier since you can just use BYREF, but with other languages assume always BYVAL and simply state the value is a pointer.

    As long as those languages support some command to get a variables address, then this should not be a problem.

    Actually BYREF is a bit limiting in that the variable type is fixed (ie. a UDT)
    I often override the win32api declarations by using BYVAL in the function call.


    X& = SomeAPIFunction(SomeUDT) ' defined BYREF in declaration

    can be:

    X& = SomeAPIFunction(BYVAL STRPTR(MyString$))

    BYREF declarations force the compiler to expect a unique variable type.

    Using BYVAL and simply passing a pointer to a variable (or any other memory storage) allows you to use any data type to pass the data with.
    Last edited by Chris Boss; 17 Mar 2008, 06:17 PM.
    Chris Boss
    Computer Workshop
    Developer of "EZGUI"


      I don't believe that you should make decisions about whether an argument should be passed by value or by reference based on what is more common or preferred by more people. It should be determined by how the function is actually using the arguments that you pass to it.

      Part of implementing a well-designed API is having strict interface contracts where you limit potential side effects; allowing an argument to be passed by reference when only its value is used has the potential to violate the contract with the caller and produce unexpected results. Simply put, if the function doesn't need to modify the caller's data, don't give it the opportunity to do so.

      So, if the function considers the argument to effectively be "read only" and should not change the caller's data that is being passed to it, then it should be passed by value. On the other hand, if the data being passed must be modified by the called function and returned to the caller, then it must be passed by reference.

      Another consideration for passing arguments by value as a "default" is that some languages simply don't handle passing values by reference very well. Because they don't support the concept of pointers to data, or don't make it very easy, passing everything by reference unnecessarily forces the developer to use workarounds for every argument, such as treating a pointer as a 32-bit unsigned integer value and so on.
      Mike Stefanik


        To add to Mikes comments:

        Normally all parameters should be pased BYVAL.

        BYREF (or BYVAL passing a pointer) has its place such as:

        - The need to have a value returned in the parameter. A function can return one value, but passing multiple BYREF parameters allows returning multiple values.

        - The need to pass a block of data (a buffer). This could be an array or simply a buffer. By using a pointer to the buffer, the calling program does not have to support a specific data type. For example, if the language does not support the data type, it can often be "faked" using a different type, such as a string or a long array. Faking a data type for a structure allows more languages to use the DLL. For example, PB does not have a native Unicode data type, but it can be faked by using standard strings and simply fill it with unicode data. A languages may not support asciiz, but it could be faked using a variety of data types (ie. array of bytes). Passing some data types as a pointer (or BYREF) allows more flexibility in calling it from more languages (as long as they support pointers).
        Chris Boss
        Computer Workshop
        Developer of "EZGUI"


          It you are creating a "marketable" library, use BYVAL always for parameters that will not be changed by the library. One exception is to use BYREF ASCIIZ for strings. If you need to include NULL characters, use a BYVAL BYTE PTR and a size parameter. Dynamic strings are hard to support in many non-PB languages.

          Another trap is functions AS QUAD, which are not compatible with the major languages, you are fine with BYVAL/BYREF QUAD parameters though.
 | Slam DBMS | PrpT Control | Other Downloads | Contact Me


            Another vote for ByVal.

            If you got a bug in your DLL, using ByVal, you'll at least don't mess with the contents passed to you from the caller.



              In my limited experience with another language, I found that its default was BYVAL. Therefore I had to use long varables to pass the literal values BYREF.


                Thanks everyone for your contribution.
                I guess BYVAL it is, then ..

                Kind regards