QB64 Phoenix Edition
DAY 031: BYVAL - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: Official Links (https://qb64phoenix.com/forum/forumdisplay.php?fid=16)
+--- Forum: Learning Resources and Archives (https://qb64phoenix.com/forum/forumdisplay.php?fid=13)
+---- Forum: Keyword of the Day! (https://qb64phoenix.com/forum/forumdisplay.php?fid=49)
+---- Thread: DAY 031: BYVAL (/showthread.php?tid=1267)



DAY 031: BYVAL - Pete - 12-12-2022

SYNTAX

For us Rednecks... I like ta BYVAL, Pat. I'd like a P.

For everyone else...

BYVAL

So all this really is is a way to tell the system we will be passing a variable in a library variable list by value rather than by reference. We are basically defining the passing mechanism.

So what's the difference you ask?

In short, passing by value passes the actual value of the variable to the sub-procedure, and back.

Passing by reference means we can mess with the variable name from the call list to the library, sub, or function, and modify the programming element underlying the argument in the calling code. The position in the list is all that matters.

Here is a sub example of passing two variables by reference...

Code: (Select All)
CALL Pete(smart, ascii) ' But not on weekends and not past 5pm M-F.
PRINT smart, ascii

SUB Pete (dumb, ascii)
    dumb = -1
    ascii = 1
END SUB

Output -1, 1

So in this reference example, we see the variable value of dumb got passed by reference to the variable, "smart".

On the other hand, passing by value would mean the value of the variable assigned to the name of the variable would remain the same. So the code would need to be changed from dumb =-1 to smart = -1 to get the same output, but...

Sorry, I can't demo BYVAL in a sub or function, because this keyword is only available for use in  DECLARE LIBRARY statements.

So here is a Windows example to minimize and maximize the window using BYVAL in a DECLARE Library statement...

Code: (Select All)
DECLARE DYNAMIC LIBRARY "user32"
    FUNCTION ShowWindow& (BYVAL hwnd AS LONG, BYVAL nCmdShow AS LONG) 'maximize process
END DECLARE

hWnd& = _WINDOWHANDLE

_KEYCLEAR
PRINT "Press a key to minimize this window and then press a key again to restore it..."
SLEEP
y& = ShowWindow&(hWnd&, 2) ' Minimize
_KEYCLEAR
SLEEP
PRINT: PRINT "We're back!"
y& = ShowWindow&(hWnd&, 9) ' Restore

If anyone has any example(s) that work in Linux, or Mac; or any additional info to post, feel free.

Right now, I have to solve the puzzle...

_ _ c k    J _ _    B _ d _ n

Let's Go Brandon!


RE: DAY 031: BYVAL - mnrvovrfc - 12-12-2022

"BYVAL" and "BYREF" are all over the place in Freebasic code which is just sad. Meanwhile QB64(PE) has to align with Q(uick)BASIC more often, that's why this "BYVAL" has bit the programmer many times (like myself) who thinks he/she is slicker than the system.

This need for "BYVAL" got me several times while doing "dot-H" routines.


RE: DAY 031: BYVAL - SpriggsySpriggs - 12-14-2022

BYVAL should be used anytime you are not passing a string.


RE: DAY 031: BYVAL - Pete - 12-14-2022

(12-14-2022, 05:01 PM)Spriggsy Wrote: BYVAL should be used anytime you are not passing a string.

Good point, +1


RE: DAY 031: BYVAL - SMcNeill - 12-14-2022

User Defined Types as well, from what I remember, should usually be passed without BYVAL. 

And maybe arrays?  Honestly, I don't think I've passed enough arrays through any sort of DECLARE LIBRARY interface enough times to ever remember doing it.  I *think* you'd probably want to pass them without BYVAL, but I wouldn't swear to it.  Anyone ever did much array passing with the DECLARE LIBRARY routines, who could give us a simple example?


RE: DAY 031: BYVAL - SpriggsySpriggs - 12-14-2022

Anything numeric should always be passed as BYVAL. I don't pass user-defined types to an external library without using _OFFSET. Arrays can be passed as _OFFSET as well.


RE: DAY 031: BYVAL - Pete - 12-14-2022

Correct on UDTs, Steve...

Example

Code: (Select All)
FUNCTION GetCursorPos (lpPoint AS POINTAPI)


POINTAPI is a UDT. Put BYVAL in there and it won't compile.

TYPE POINTAPI
    X_Pos AS LONG
    Y_Pos AS LONG
END TYPE

I haven't had any experience with arrays though. Now I've successfully accomplished defining the variables as LONG, instead of passing them as _OFFSET, so I needsome more clarification from Spriggsy I guess.

Pete


RE: DAY 031: BYVAL - mnrvovrfc - 12-14-2022

This is just my guessing. If an array is contiguous in memory, create a "_MEM" variable to point to the first element of the array and find a way to pass also the total size of the array. For example for "DIM A(1 to 20) AS LONG" have a "DIM AM AS _MEM" then "AM = _MEM(A(1))", somehow make an _OFFSET out of "AM" (I believe "AM.OFFSET") and then pass an array size value of 80 bytes.

Would have to indicate the size of the UDT variable also besides the _OFFSET.


RE: DAY 031: BYVAL - SpriggsySpriggs - 12-14-2022

Most external libraries (WinAPI especially) will expect things like arrays or structs to be passed as a pointer. _OFFSET allows us to pass the pointer to these items. You'd do

_OFFSET(myArray()) or _OFFSET(myUDT)

You just want to make sure that the argument for the function is BYVAL so it gets the value of the address.

WinAPI to QB64:
BYTE -> BYTE
WORD -> UNSIGNED INTEGER
DWORD -> UNSIGNED LONG
QWORD -> UNSIGNED INTEGER64
void* or most arguments that start with "h" or "p", handles -> OFFSET

Handles/pointers/"h"/"p" are 4 bytes in 32 bit and 8 bytes in 64. We use OFFSET for these to automate this switching of size.

All of the above would be passed with BYVAL