Posts: 177
Threads: 37
Joined: Jul 2022
Reputation:
6
I have been using this code for awhile. It is a CreateFile library function call.
Problem it work in Qb64pe-32 bit but in 64-bit throws a GNU C++ compilation error and I wanted to know why!?
Erik.
Code: (Select All) Rem $Dynamic
DefLng A-Z
Declare Dynamic Library "kernel32"
Function CloseHandle& (ByVal hfile As _Offset)
End Declare
Rem hfind = CreateFileA(ASCIIZ, &H180, &H3, 0, 3, 0, 0)
' parameters:
' (1) pointer to filename
' (2) access:
' x80(128) - read
' x100(256) - write
' (3) sharing
' (4) security attributes
' (5) create file flag
' (6) flags (standard OSHA)
' (7) pointer to template file
' paramater 5
' 0 DEFAULT_OPEN_EXISTING = open only if exists
' 1 CREATE_NEW = create only if not exist
' 2 CREATE_ALWAYS = always create new file
' 3 OPEN_EXISTING = open only if exists
' 4 OPEN_ALWAYS = open file always
' 5 TRUNCATE_EXISTING = open/truncate to 0 only if exists
' 6 OPEN_DIRECTORY = open if directory exists
Declare Library
Function CreateFileA& (filename$, Byval access&, Byval sharing&, Byval sec_attr%&, Byval create&, Byval flags&, Byval template%&)
End Declare
Dim hfind As _Offset
' detect file
Print "Enter filename";
Input f$
If Len(f$) Then
f$ = f$ + Chr$(0)
hfind = CreateFileA(f$, &H180, 0, 0, 3, 0, 0)
If hfind Then
Print "File exists."
r = CloseHandle(hfind)
End If
End If
End
Posts: 217
Threads: 12
Joined: Apr 2022
Reputation:
31
'CreateFileA' returns a HANDLE, which should be treated as an _Offset , but you wrote it as CreateFileA& , so the return value is treated as a 32-bit LONG .
The C++ compiler isn't allowing you to make the mistake of casting the HANDLE value to a LONG (which is what QB64 will do to make your function definition work) because that's always a bug on 64-bit systems and chops-off the top-half of the 64-bit HANDLE value, making it useless.
Posts: 177
Threads: 37
Joined: Jul 2022
Reputation:
6
So if I modify the handle to:
Code: (Select All) Dim hfind As _Unsigned Long
it should work on 64-bit qb64?
Erik.
Posts: 217
Threads: 12
Joined: Apr 2022
Reputation:
31
(06-05-2023, 10:35 PM)eoredson Wrote: So if I modify the handle to:
Code: (Select All) Dim hfind As _Unsigned Long
it should work on 64-bit qb64?
Erik.
You got it backwards. You correctly declared hfind as an _Offset type, but you incorrectly declared the return type of CreateFileA to be a Long instead of an _Offset . You need to declare it as CreateFileA%& so that QB64 knows it returns an _Offset type.
Posts: 177
Threads: 37
Joined: Jul 2022
Reputation:
6
Can you tell me if this is correct..
Code: (Select All) Rem $Dynamic
DefLng A-Z
Declare Dynamic Library "kernel32"
Function CloseHandle& (ByVal hfile As _Offset)
End Declare
Rem hfind = CreateFileA(ASCIIZ, &H180, &H3, 0, 3, 0, 0)
' parameters:
' (1) pointer to filename
' (2) access:
' x80(128) - read
' x100(256) - write
' (3) sharing
' (4) security attributes
' (5) create file flag
' (6) flags (standard OSHA)
' (7) pointer to template file
' paramater 5
' 0 DEFAULT_OPEN_EXISTING = open only if exists
' 1 CREATE_NEW = create only if not exist
' 2 CREATE_ALWAYS = always create new file
' 3 OPEN_EXISTING = open only if exists
' 4 OPEN_ALWAYS = open file always
' 5 TRUNCATE_EXISTING = open/truncate to 0 only if exists
' 6 OPEN_DIRECTORY = open if directory exists
Declare Library
Function CreateFileA%& (filename$, Byval access&, Byval sharing&, Byval sec_attr%&, Byval create&, Byval flags&, Byval template%&)
End Declare
Dim hfind As _Offset
' detect file
Print "Enter filename";
Input f$
If Len(f$) Then
f$ = f$ + Chr$(0)
hfind = CreateFileA(f$, &H180, 0, 0, 3, 0, 0)
If hfind Then
Print "File exists."
Print "Handle: "; Hex$(hfind)
r = CloseHandle(hfind)
End If
End If
End
If the entire problem is with the function declaration then I have got it wrong the whole time.
Posts: 1,510
Threads: 53
Joined: Jul 2022
Reputation:
47
In 64-bit _UNSIGNED LONG sometimes won't be good enough, and it won't be toward a parameter that expects a pointer. It's because LONG in QB64 is always 32-bit. It needs to be _INTEGER64 or better yet, _OFFSET.
When converting 32-bit code to 64-bit be prepared to turn any LONG or _UNSIGNED LONG into _OFFSET, or less frequently _INTEGER64. But it depends on the context, such as that "size_t" that seems to be declared as different type in each C/C++ header file.
Pointers are really a PITA which is why I gave up soon with C programming. Was repeatedly crashing my computer trying to program a cheap window manager out of the equivalent of SCREEN 0 limited to MS-DOS, many many years ago.
Posts: 217
Threads: 12
Joined: Apr 2022
Reputation:
31
(06-05-2023, 11:58 PM)eoredson Wrote: If the entire problem is with the function declaration then I have got it wrong the whole time. The code looks good to me, and seems to work
Yes it was technically wrong the whole time. The catch is that because _Offset is 32-bits wide in 32-bit QB64, and a Long is also 32-bits wide, using CreateFileA& happens to work anyway when using 32-bit QB64. It's only when using 64-bit QB64 that the _Offset vs Long distinction matters.
To make your code portable between 32-bit and 64-bit you should ensure you use _Offset for any value that needs to vary in size depending on the platform (That goes for all pointer types, such as HANDLE in Win32).
Posts: 177
Threads: 37
Joined: Jul 2022
Reputation:
6
That helps and is a real pita because:
32-bit = Long/_Unsigned Long
64-bit = _Integer64/_Offset
never seemed clear to me because of the function declaration is CreateFile%& as well..
Erik.
Posts: 177
Threads: 37
Joined: Jul 2022
Reputation:
6
My ultimate goal was to make sure my projects are cross-platform compatible between 32-bit and 64-bit.
I can't test this fact since I have no 64-bit version of Qb64pe that ever worked very well..
If I can get around the compilation errors then I can test the code.
Posts: 217
Threads: 12
Joined: Apr 2022
Reputation:
31
(06-06-2023, 01:34 AM)eoredson Wrote: That helps and is a real pita because:
32-bit = Long/_Unsigned Long
64-bit = _Integer64/_Offset
never seemed clear to me because of the function declaration is CreateFile%& as well..
Erik. That's note quite right, _Offset is not the same thing as _Integer64 .
_Offset is special, it is 32-bits wide on 32-bit QB64, and 64-bits wide on 64-bit QB64. It is a different size depending on the version used, which is also why you need to use it to represent types like HANDLE which also differ in size in C++ depending on the platform. To make cross-platform programs you have to use _Offset to represent C++ types like pointers which are a different size on different platforms.
|