en en en en en en en en en en en en en en en en en en en en en en en en en en en mr en en en en en en en en en en en en en en en en en en en en en en en nl en mr en en en en en en en en en en en de en en en en en nl en en en en en en en en nds en en en en nl en en en en en en en en en en en en en en en nl en en en en en en en fr en da en en en en en en en nl en en en en en en fr en da en en en en en en en nl en en en en en en en en en en en en en nds en en en en nl vi en en en en en en en en en en en en nl en en en en en en en en en en en en nl fr en en en en en en fr en da en en en en de en en en fr en en en en en en en en en pt en en en en en en
By logging into your account, you agree to our Privacy Policy, personal data processing and storage practices as described therein.
Forgot password or user name?
Search in titles only Search in PowerBASIC for Windows only
You are not logged in. You can browse in the PowerBASIC Community, but you must click Login (top right) before you can post. If this is your first visit, check out the FAQ or Sign Up.
Optional ByVal Parameter Change In Behavior
All Time Today Last Week Last Month
All Discussions only Photos only Videos only Links only Polls only Events only
I've just come across one of my PBWin 8.04 programs that won't compile 'as is' with PBWin 9, and I'm not sure whether this is significant or not. Its a short program some of you might remember from last fall when I was working with using the C Runtime Library's printf for console output with PBWin. The program declares the printf function like so...
Declare Function printf CDecl Lib "msvcrt.dll" Alias "printf" _ 'printf from stdio.h ( _ szFmtStr As Asciiz _ [, _ Byval lpVar1 As Any, _ Byval lpVar2 As Any, _ Byval lpVar3 As Any, _ Byval lpVar4 As Any _ ] _ ) As Long
The PBWin error message states 'Byval parameter not allowed'. The documentation for optional parameters shows Byval examples with optional parameters, but it doesn't work for me. I don't know if the 'As Any' has anything to do with it. Getting the program to work isn't too much trouble though. All that needs done is to remove the four 'ByVal' keywords from the Declare, and put ByVal overrides in front of parameters passed to the printf function as in...
printf("%d" + Chr$(9) + "My Name Is Fred And I Weigh %u Pounds!"+$Cr+$Lf, Byval i, Byval dwWeight)
Here is the program again. If those changes are made it works. I will admit this is a rather unusual use of PowerBASIC, and pushes things pretty far.
'Program demonstrates how to restore standard output handle in C Runtime Library 'which is zeroed out by initialization of GUI process. #Compile Exe #Include "Win32api.inc" 'Translation of Windows.h for PowerBASIC %IDC_BUTTON1 = 1250 'ctrl id of button %O_TEXT = &H4000 'from Fcntl.h Type FILE 'From stdio.h 'When a GUI application is started the three standard OS handles pChar As Asciiz Ptr 'STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, and STD_ERROR_HANDLE are all cnt As Long 'zeroed out by the console initialization routines. These three pBase As Asciiz Ptr 'handles are replaced by valid values when a GUI application calls flag As Long 'AllocConsole(). Therefore, once this is done, calling GetStdHandle() fil As Long 'will always return valid handle values. The problem is that the charbuf As Long 'CRT has already completed initialization before an application gets bufsize As Long 'a chance to call AllocConsole(); the three low I/O handles 0, 1, TmpFileName As Asciiz Ptr 'and 2 have already been set up to use the original zeroed out OS End Type 'handles, so all CRT I/O is sent to invalid OS handles and CRT output 'does not appear in the console. Declare Function GetConsoleWindow Lib "Kernel32.dll" Alias "GetConsoleWindow" () As Dword Declare Function printf CDecl Lib "msvcrt.dll" Alias "printf" _ 'printf from stdio.h ( _ szFmtStr As Asciiz _ [, _ Byval lpVar1 As Any, _ Byval lpVar2 As Any, _ Byval lpVar3 As Any, _ Byval lpVar4 As Any _ ] _ ) As Long Declare Function Open_OSFileHandle CDecl Lib "msvcrt.dll" Alias "_open_osfhandle" _ 'from IO.h ( _ Byval hHandle As Long, _ Byval iType As Long _ ) As Long Declare Function FDOpen CDecl Lib "msvcrt.dll" Alias "_fdopen" _ 'from stdio.h ( _ Byval hHandle As Long, _ ByRef pszStr As Asciiz _ ) As Dword Function WndProc(Byval hWnd As Long,Byval wMsg As Long,Byval wParam As Long,Byval lParam As Long) As Long Select Case wMsg Case %WM_CREATE Local hButton As Dword Local hIns As Dword hIns=GetModuleHandle(Byval 0) hButton=CreateWindow("button","Show Console!",%WS_CHILD Or %WS_VISIBLE,110,65,200,25,hWnd,%IDC_BUTTON1,hIns,Byval 0) WndProc=0 Exit Function Case %WM_COMMAND If Lowrd(wParam)=%IDC_BUTTON1 And HiWrd(wParam)=%BN_CLICKED Then Local hStdOutput As Dword 'Standart Output Handle Local hf,ptrFile As FILE Ptr 'FILE * Local hDll,hCrt,dwWeight As Dword Local hSysMenu As Dword Register i As Long hDll=LoadLibrary("msvcrt.dll") 'Load/Increment Reference Count on msvcrt.dll If hDll Then 'Get base address of exported symbol _iob from msvcrt.dll. _iob is an ptrFile=GetProcAddress(hDll,"_iob") 'array of FILE structs that holds the stdin, stdout, and stderr handles. Call AllocConsole() 'These handels are zeroed out at initialization of a GUI process, and hSysMenu=GetSystemMenu(GetConsoleWindow(),Byval 0) 'must be reset with valid operating system handles if Call DeleteMenu(hSysMenu,6,%MF_BYPOSITION) 'console output is desired in a GUI process. With a hCrt=Open_OSFileHandle(GetStdHandle(%STD_OUTPUT_HANDLE),%O_TEXT) 'valid handel to stdout returned in hf, it hf=FDOpen(hCrt,"w") 'is restored back in position 1 of the i/o buffer FILE array with @ptrFile[1][email protected] '@[email protected] printf output using CRT in PowerBASIC! dwWeight=210 For i=1 To 200 ' printf("%d" + Chr$(9) + "My Name Is Fred And I Weigh %u Pounds!"+$Cr+$Lf,i,dwWeight) Next i Call FreeLibrary(hDll) 'Free/decrement reference count on msvcrt.dll End If End If WndProc=0 Exit Function Case %WM_DESTROY Call PostQuitMessage(0) WndProc=0 Exit Function End Select WndProc=DefWindowProc(hWnd, wMsg, wParam, lParam) End Function Function WinMain(Byval hIns As Long, Byval hPrev As Long, Byval lpCL As Asciiz Ptr, Byval iShow As Long) As Long Local szBuffer As Asciiz * 64 Local wc As WNDCLASSEX Local Msg As tagMsg Local hWnd As Dword szBuffer="Console_Output" : wc.lpszClAssName=Varptr(szBuffer) wc.lpfnWndProc=Codeptr(WndProc) : wc.cbSize=Sizeof(wc) wc.style=%CS_HREDRAW Or %CS_VREDRAW : wc.hInstance=hIns wc.cbClsExtra=0 : wc.cbWndExtra=0 wc.hIcon=LoadIcon(%NULL, Byval %IDI_APPLICATION) : wc.hCursor=LoadCursor(%NULL, Byval %IDC_ARROW) wc.hbrBackground=%COLOR_BTNFACE+1 : wc.lpszMenuName=%NULL Call RegisterClAssEx(wc) szBuffer="GUI Console Output With C Runtime Library From PowerBASIC!" hWnd=CreateWindow("Console_Output",szBuffer,%WS_OVERLAPPEDWINDOW,500,550,440,200,0,0,hIns,Byval 0) Call ShowWindow(hWnd,iShow) Call UpdateWindow(hWnd) While GetMessage(Msg,%NULL,0,0) TranslateMessage Msg DispatchMessage Msg Wend Function=msg.wParam End Function
Join Date: Aug 1998
26 Aug 2008, 12:23 PM
Think about for minute Fred. What does BYVAL as ANY Mean????
What if I pass a 128 byte asciiz string???
I believe it was a unwanted feature from previous versions??
Join Date: Sep 2000
26 Aug 2008, 01:25 PM
Declare Function wsprintf CDecl Lib "USER32.DLL" Alias "wsprintfA" (lpOutput As Asciiz, lpFormat As Asciiz, x As Any, Optional x1 As Any, Optional x2 As Any, Optional x3 As Any, Optional x4 As Any, Optional x5 As Any, _ Optional x6 As Any, Optional x7 As Any, Optional x8 As Any, Optional x9 As Any, Optional x10 As Any, Optional x11 As Any, Optional x12 As Any) As Long
Note that all the parameters are BYREF (as the function expects). Since the function is CDECL, the caller will "clear up" the stack as it knows exactly how many pointers were passed, and the function will know what data to expect from the parameters used in the format string. PB has defined 13 (0-12) "data" variables for wsprintf(), but it can be as many as you are going to need -- right up to the maximum of 30 (2 strings + 30 data variables = 32).
Last edited by Kev Peel; 26 Aug 2008, 01:27 PM.
kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me
Join Date: Aug 1998
26 Aug 2008, 01:30 PM
It's 'BYVAL AS ANY' which makes no sense.
'BYREF AS ANY' does make sense... the called routine is responsible to know what it expects in which parameter position.
Port Washington WI USA
Join Date: Aug 1998
26 Aug 2008, 01:32 PM
>Declare Function Open_OSFileHandle CDecl Lib "msvcrt.dll"....
Port Washington WI USA
Join Date: Jan 2000
26 Aug 2008, 03:21 PM
Well then why does one need to put a Byval override in front of every parameter one wishes to output with these printf family functions if one wishes to obtain the correct result? For example - and using Kev's wsprintf function, here is a Console Compiler program that gives the same incorrect result with either PBCC 4 or 5 using the declare in Win32Api.inc.
#Compile Exe #Dim All #Include "Win32Api.inc" Function PBMain () As Long Local szBuffer As Asciiz*64 Local iLen, iNum As Long iNum = 25 iLen=wsprintf(szBuffer,"iNum = %u",iNum) Print szBuffer Waitkey$ PBMain=0 End Function ' 'Output: '======= 'iNum = 1244704
If that declare was right, the correct answer for iNum should have been output. The correct answer is 25 - not 1244704. The latter is the virtual address where iNum is stored. If you want to get the correct answer, i.e., '25', then you need a Byval override in front of iNum in the last parameter position - like so...
#Compile Exe #Dim All #Include "Win32Api.inc" Function PBMain () As Long Local szBuffer As Asciiz*64 Local iLen, iNum As Long iNum = 25 iLen=wsprintf(szBuffer,"iNum = %u",Byval iNum) Print szBuffer Waitkey$ PBMain=0 End Function 'Output: '======= 'iNum = 25
Or am I hopelessly screwed up in my thinking???
Join Date: Sep 2000
26 Aug 2008, 03:36 PM
The wsprintf() function seems to use a "virtual byval" for numerics and the address passed is actually used as a data value. To prove my point, try the same code with "%s" and use a ASCIIZ string, or just pass "BYVAL 25" - both will work.
This method is also used with the resource functions - you pass a resource ID using a BYVAL numeric (0-64k), or a BYREF string address. It all depends on the function being called, and in this case, using BYREF ANY is correct.
kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me
Join Date: Jan 2000
26 Aug 2008, 03:58 PM
Hmm. I see what you mean Kev. I hadn't ever tried it with strings. What it seems to boil down to is that whichever way the function is declared, either numerics or strings will be awkward. For example, if the functions are declared as I did my original last fall, that is, optional byval, then if you are doing a string, i.e., %s, then you need a VarPtr(szString) passed. If the function is declared as PowerBASIC has it and as it apparently has to be declared with PB5 - PB9, then a byval override needs to be placed in front of every numeric parameter.
Join Date: Aug 1998
26 Aug 2008, 06:59 PM
Correct conversion is: USING$
Sheesh, two "functions to port " in one thread, where port is not necessary because PB includes intrinsic support for both.
Anyone still wonder why I say verb-for-verb, function-for-function conversions are stone losers?
Port Washington WI USA
Copyright © 1998-2022 PowerBASIC Tools, LLC - All Rights Reserved.
Powered by vBulletin® Version 5.7.0
Copyright © 2022 vBulletin Solutions, Inc. All rights reserved.
All times are GMT-5. This page was generated at 03:47 AM.
We process personal data about users of our site, through the use of cookies and other technologies, to deliver our services, and to analyze site activity. For additional details, refer to our Privacy Policy.
By clicking "I AGREE" below, you agree to our Privacy Policy and our personal data processing and cookie practices as described therein. You also acknowledge that this forum may be hosted outside your country and you consent to the collection, storage, and processing of your data in the country where this forum is hosted.