Lazarus
Installation => Windows (32/64) => Topic started by: poiuyt555 on June 25, 2013, 05:15:40 am
-
Hi.
I have some project and i want to compile it on 64-bit Lazarus.
I use official releases:
lazarus-1.0.10-fpc-2.6.2-win32.exe
lazarus-1.0.10-fpc-2.6.2-win64.exe
Is any difference, problems of porting 32-bit app to 64-bit?
I ask it because i have some problems, some functions not working properly in 64-bit Lazarus. (soon i post here the description of problems). Now i ask in general case.
-
In the documentation
http://wiki.freepascal.org/Code_Conversion_Guide#32bit_.2F_64_bit_support
-
Thanks, user137.
I will see your link, and now i post here the first problem:
Windows 7 64-bit.
lazarus-1.0.10-fpc-2.6.2-win32.exe
lazarus-1.0.10-fpc-2.6.2-win64.exe
Problem #1:
This code compiles without errors in 32-bit LAzarus, but didn't compiles in 64-bit:
uses
...windows...
...
var
Form1: TForm1;
OldWProc : WNDPROC = nil;
...
function MyWndProc(hWnd: HWND; uiMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
//
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
OldWProc := Windows.WNDPROC(SetWindowLong(Handle, GWL_WNDPROC, Integer(@MyWndProc)));
end;
On line OldWProc := ... in 64-bit Lazarus it gave me an error:
Error: Illegal type conversion: "LongInt" to "<procedure variable type of function(QWord,LongWord,Int64,Int64):Int64;StdCall>"
How to fix it?
-
@MyWndProc returns a 64-bit address (when compiled with 64-bit compiler). Even if you did convert it into 32-bit integer first, you would lose information. This truncated address would not be useful for the receiving end.
I mean, PtrInt(@MyWndProc) might compile, but not work as you wanted.
-
Ptrint is a signed integer type which has always the same size as a pointer.
Reference : http://www.freepascal.org/docs-html/rtl/system/ptrint.html (http://www.freepascal.org/docs-html/rtl/system/ptrint.html)
-
And SetWindowLong expects LONG type as the last argument, so casting to Integer is not really valid. Since you target Windows only, LONG is also available (perhaps along with TLONG) so you can directly use that instead.
-
Thanks to all!
When i replace integer() to PtrInt() - the same error:
OldWProc := Windows.WNDPROC(SetWindowLong(Handle, GWL_WNDPROC, PtrInt(@MyWndProc)));
Error: Illegal type conversion: "LongInt" to "<procedure variable type of function(QWord,LongWord,Int64,Int64):Int64;StdCall>"
When i replace SetWindowLong to SetWindowLongPtr it compiles:
OldWProc := Windows.WNDPROC(SetWindowLongPtr(Handle, GWL_WNDPROC, PtrInt(@MyWndProc)));
Q1: Is it correct way to solve this problem?
Q2: Is it backward compatibly with 32-bit compiler?
-
Question # 2:
Why FindAllFiles('c:\') compiled with 64-bit compiler (c - system drive) gives about +1500 files more than compiled with 32-bit compiler on my Win7-64bit.
-
Use the cross-platform functions provided by FPC libs and LCL, instead of WinAPI. They work for 32- and 64-bits without tweaking.
I don't know why many people still want to use the ancient WinAPI while there is a better cross-platform solution. Maybe WinAPI should be deprecated somehow.
-
Q1: Is it correct way to solve this problem?
Q2: Is it backward compatibly with 32-bit compiler?
That works fine both 32/64.
I've had only few problems while testing 64bit. Using registry did not work properly, and had to make changes. If there is need to disable fpu exceptions, set8087CW($133F); does not help in 64, SetExceptionMask from "math" is needed.
I don't know why many people still want to use the ancient WinAPI
for example Application.OnMessage is missing from Lazarus. This has actually been biggest problem converting Delphi applications. I have solved it using winapi, there is no other way.
-
for example Application.OnMessage is missing from Lazarus. This has actually been biggest problem converting Delphi applications. I have solved it using winapi, there is no other way.
There is no cross-platform solution for Application.OnMessage, it is too Windows specific.
What do you want to do in that event? The same thing can always be implemented differently, although it may require rewriting and refactoring somewhat.
-
The same thing can always be implemented differently
I need all kind of mouse / keyboard / window messages.
For example following simple Delphi code is quite impossible. It captures (and eats) all right mouse clicks. No matter what component is under mouse.
private
procedure MsgHandler(var Msg: TMsg; var Handled: Boolean);
procedure TForm1.MsgHandler(var Msg: TMsg; var Handled: Boolean);
var M: TPoint;
begin
if Msg.message=WM_RBUTTONDOWN then
begin
GetCursorPos(M);
label1.caption:='Right mouse click '+inttostr(M.X)+' '+inttostr(M.Y);
handled:=true; //"Eat" this message
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
application.OnMessage:=MsgHandler;
end;
-
Thanks JuhaManninen, Timewarp.
Use the cross-platform functions provided by FPC libs and LCL, instead of WinAPI.
But FindAllFiles - this is the Lazarus modern functionality, as i understand.
FindAllFiles is located in FileUtil unit, and is using TFileSearcher.Search method to find for files, which is using FindFirstUTF8/FindNextUTF8, which is using probably, yes, winAPI.
Ex. one of those files which was is not found by 32-bit compiled program:
C:\Windows\system32\7B296FB0-376B-497e-B012-9C450E1B7327-5P-0.C7483456-A289-439d-8115-601632D005A0
How can you explain this results?
What is it, from where this files?
-
All Windows 64-bit versions redirect certain system folders and system registry entries when 32-bit program tries to access them. Only 64-bit program sees these entries fully.
See http://en.wikipedia.org/wiki/WoW64 for more info.
-
Thanks, Cyrax.
I guess that I understood.
Problem #3:
this code gives me different results on 32 or 64 bit compiler:
var tr: string;
begin
SetLength(tr, MAX_PATH);
if not SHGetSpecialFolderPath(0, PChar(tr),CSIDL_PROGRAM_FILES, true) then tr := '';
result :=PChar(tr);
end;
Compiled with 32-bit compiler:
- when windows is 32-bit - it returns c:\program files
- when windows is win7 64-bit - it returns c:\program files (x86)
And this is correct for me, but
Compiled with 64-bit compiler:
- when windows is win7 64-bit - it returns c:\program files but not c:\program files (x86)
And if i use flag CSIDL_PROGRAM_FILESX86 - it return correct c:\program files (x86)
But in that case it will be not backward compatibly with 32-bit mode.
Why it is so?
How to fix it?
-
It's by design. Under 64-bit Windows 64-bit programs goes under "Program Files" and 32-bit ones under "Program Files (x86)". Why do you need it to be compatible, anyway?
-
It seems to me already to be 'plug and play' unless you have some specific code that requires to do unique stuff. 64-bit programs does 64-bit stuff (can't call 32-bit stuff and vice versa) and 32-bit does 32-bit stuff.
-
I need all kind of mouse / keyboard / window messages.
For example following simple Delphi code is quite impossible. It captures (and eats) all right mouse clicks. No matter what component is under mouse.
[...]
True, it is not currently possible.
TOnUserInputEvent in Application lets you see and react to all mouse events. Unfortunately it does not let you "eat" or filter out the events.
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.AddOnUserInputHandler(@UserInputHandler);
end;
procedure TForm1.UserInputHandler(Sender: TObject; Msg: Cardinal);
begin
...
end;
There are other Application.AddOn... methods for other events, too.
It should be possible to extend OnUserInputEvent + handler to take a var param which you can change.
If you want to dive into LCL events and create a patch for such feature, I think it can be applied.
How much work or side-effects it causes, I have no idea.