Lazarus

Programming => General => Topic started by: BosseB on March 29, 2023, 11:43:27 pm

Title: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 29, 2023, 11:43:27 pm
I need to implement specific hardware functionality using Delphi7 because of interfacing issues for the hardware access that cannot be implemented with FreePascal.
So I was thinking of building an IPC comm channel, but how can that be done between a 64 bit Lazarus/Fpc app and a Delphi7 32 bit "server"?

I found this example (https://forum.lazarus.freepascal.org/index.php?action=dlattach;topic=43489.0;attach=29356) on another thread here (https://forum.lazarus.freepascal.org/index.php/topic,43489.msg304434.html#msg304434) which discusses IPC comm.
However this implements both sides using Lazarus/Fpc for both server and client...
How can I build the Delphi7 server such that it can serve the Lazarus client?

I have not done something like this  previously and I do not want to bring up  TCP/IP comm or the like. The Delphi7 app shall implement a small number of commands for which it will return a response when called. That is all.

Calls can come from one or several FreePascal applications and they typically only do this very sparingly with hours in between (but always when they start up).

Any ideas/suggestions?
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: jamie on March 29, 2023, 11:53:39 pm
what specifics are stopping you to use FPC/Laz ?
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: Zvoni on March 30, 2023, 12:01:52 am
Adding to jamie: IPC between 32-bit and 64-bit your best bet usually is Sockets
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: jamie on March 30, 2023, 12:26:18 am
DDE/DDEML ?
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: KodeZwerg on March 30, 2023, 12:38:15 am
Or via simple oldschool MMF ....
Demo attached.
Compile "Delphi32" folder first and run and press a button.
Compile "Lazarus64" folder second and run and press button.

Compare values inside the memo's.
On my Win10/64bit system it works.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 30, 2023, 12:48:19 am
what specifics are stopping you to use FPC/Laz ?
I use software protection dongles originally from Rainbow Sentinel.
There is an SDK to interface with the driver they provide, and it works in Delphi7.
But when I try to port even the simplest application from D7 to Fpc it won't build because the SDK provides an obj file that implements all the API calls into the driver and the obj file generates an error when linking...

I have even gotten an updated SDK from the company with a new obj file, but that too fails. The syntax check completes successfully but when I compile I get the linker error where Fpc does not get to grips with the obj file.

There are 2 different obj files depending on the type of Delphi compiler, one for 32 bit (like Delphi7) and one for 64 bit Delphi.
I stopped using Delphi before it went 64 bit so I cannot check it.

So my "solution" now seems to be to implement a mini IPC server in Delphi7, which talks to the driver via the API provided (this works with the obj file).
In this I will translate all the used calls from the main application to the driver and send these as commands via the IPC channel.

So I need to implement the server with Delphi7 (32bit) and the client with Fpc/Lazarus (64 bit) using some kind of IPC channel.

Never done this before so I am on unknown grounds.
1) Can it be done?
2) What kind of object can I use that exists in both D7 and FPC 3.2.2?
3) Can it even be done at all? I mean 32bit <=>64bit?
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: jamie on March 30, 2023, 12:58:22 am
Must be the differences of Obj File formats.
COFF etc..

Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 30, 2023, 12:59:39 am
Or via simple oldschool MMF ....
Demo attached.
Compile "Delphi32" folder first and run and press a button.
Compile "Lazarus64" folder second and run and press button.

Compare values inside the memo's.
On my Win10/64bit system it works.
Thanks, I was writing my other response while you posted...
Grateful for examples like this with both ends!

I noticed that both of the sample applications were GUI style apps, is that a requirement for them to work?
I mean do they utilize the Windows message handler that requires a window to talk to?

The server in this case should not be visible (the Delphi7 app) while the client does have a visible form.
In fact one problem is how to start it running when the main app starts...

Also in principle there can be several instances of the client apps running at the same time, so does that work?
Do they get different MMF instances into the same server?

It is late now so I will test tomorrow..
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 30, 2023, 01:01:30 am
Must be the differences of Obj File formats.
COFF etc..
Yes that is the case according to other experts.
But I have no way to correct that. Must use what the supplier provides.
Apparently Fpc cannot link the obj files that Delphi can handle. :(
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: jamie on March 30, 2023, 01:05:58 am
Hmm
ok, I don't think the IPC component will work between Delphi and lazarus unless you implement it also in delphi from Laz source code?

 In any case, you can use messages to post the WM_COPYDATA message.

One app can be the server and all the clients simply post a message to it for a request etc.

 But there is one thing That may need attention when using this message, you may need to play with the message filtering in windows because it's possible this is one message that could be blocked on standard user leve.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: KodeZwerg on March 30, 2023, 01:15:01 am
Or via simple oldschool MMF ....
Demo attached.
Compile "Delphi32" folder first and run and press a button.
Compile "Lazarus64" folder second and run and press button.

Compare values inside the memo's.
On my Win10/64bit system it works.
Thanks, I was writing my other response while you posted...
Grateful for examples like this with both ends!

I noticed that both of the sample applications were GUI style apps, is that a requirement for them to work?
I mean do they utilize the Windows message handler that requires a window to talk to?

The server in this case should not be visible (the Delphi7 app) while the client does have a visible form.
In fact one problem is how to start it running when the main app starts...

Also in principle there can be several instances of the client apps running at the same time, so does that work?
Do they get different MMF instances into the same server?

It is late now so I will test tomorrow..
I've just choosen GUI for easier demonstration, it is no requirement. Anyway, you would need to poll to check for new data compared to old...
Running multiple instances of Server (Delphi32) will not work since only one can be the master in that scenario, multiple Clients (Lazarus64) are no problem.
Yeah, test and play with it a little to find out if it match your needs.

WM_COPYDATA
I dont think that sharing data between 32 and 64 bit works due different LPARAM sizes... but havent tested.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: 440bx on March 30, 2023, 03:55:57 am
Just a thought...

I would use memory mapped files for IPC, that ensures high performance and, in most cases, reasonably simple synchronization.

HTH.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: Zvoni on March 30, 2023, 11:45:08 am
What about SimpleIPC?
https://wiki.freepascal.org/SimpleIPC
https://github.com/z505/SimpleIPC-lib

On Github there is a demo for Lazarus, and a separate demo for Delphi.
No mention of 32 vs 64-Bit though
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 30, 2023, 12:17:52 pm
What about SimpleIPC?
https://wiki.freepascal.org/SimpleIPC
https://github.com/z505/SimpleIPC-lib

On Github there is a demo for Lazarus, and a separate demo for Delphi.
No mention of 32 vs 64-Bit though

It seems like it is a good way not to re-invent the wheel...

The issue I have but it can be tested I guess:
If I use this system for IPC, will it be able to communicate between 32 bit and 64 bit applications on Windows?
My only working comm case to the protection device is to use 32 bit Delphi7 as the server but my clients will obviously all be 64 bit since they are built with present day tools (normally Lazarus/Fpc).

Can a pipe or whatever it is called that it uses traverse the 32/64 bit border on Windows?
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: Zvoni on March 30, 2023, 12:33:28 pm
As far as i could find out: There should be no problem whatsoever, since you're only sending messages
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: korba812 on March 30, 2023, 12:47:53 pm
I use software protection dongles originally from Rainbow Sentinel.
There is an SDK to interface with the driver they provide, and it works in Delphi7.
But when I try to port even the simplest application from D7 to Fpc it won't build because the SDK provides an obj file that implements all the API calls into the driver and the obj file generates an error when linking...

I have even gotten an updated SDK from the company with a new obj file, but that too fails. The syntax check completes successfully but when I compile I get the linker error where Fpc does not get to grips with the obj file.

There are 2 different obj files depending on the type of Delphi compiler, one for 32 bit (like Delphi7) and one for 64 bit Delphi.
I stopped using Delphi before it went 64 bit so I cannot check it.
Try converting the .obj (COFF) file to .o (ELF) with objconv:
https://www.agner.org/optimize/#objconv
I've never tried this tool, but maybe you'll get lucky.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 30, 2023, 01:33:57 pm
What about SimpleIPC?
https://wiki.freepascal.org/SimpleIPC
https://github.com/z505/SimpleIPC-lib

On Github there is a demo for Lazarus, and a separate demo for Delphi.
No mention of 32 vs 64-Bit though

It seems like it is a good way not to re-invent the wheel...

The issue I have but it can be tested I guess:
If I use this system for IPC, will it be able to communicate between 32 bit and 64 bit applications on Windows?
My only working comm case to the protection device is to use 32 bit Delphi7 as the server but my clients will obviously all be 64 bit since they are built with present day tools (normally Lazarus/Fpc).

Can a pipe or whatever it is called that it uses traverse the 32/64 bit border on Windows?

Well,
I tried to look at the Github link to get hold of any useful files but after going back and forth I get nowhere...
I simply do not understand how I could use any of this since there seems to be a dll file involved in all examples and nowhere any download or such for that dll file...
I cannot make anything out of the examples, something is clearly missing here.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: KodeZwerg on March 30, 2023, 01:57:55 pm
IPC is not a standard, just to mention it and not that you are confused and insist to use just one method.

Interprocess Communications can be many things
- WM_COPYDATA, IMHO limited to one kind of bitness
- Clipboard, same as WM_COPYDATA but independent of bitness, downer: it may get killed by users clipboard usage
- DDE (Dynamic Data Exchange), very oldschool, not that efficiant
- File Mapping, I did show, very stable and fast, works on whatever bitness
- MailSlots, another old technology, same as DDE for me
- Pipes, can be anonymous or named pipes, should also always work
- RPC, works accurate but needs to setup a DCE (on windows/Distributed Computing Environment) plus: works independent of Operating System
- Sockets, can work great, also in a I/O way, network needs to be configured to work smooth with it

I might have forgot to mention more but those are in my mind.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 30, 2023, 02:24:22 pm
Well,
I tried to look at the Github link to get hold of any useful files but after going back and forth I get nowhere...
I simply do not understand how I could use any of this since there seems to be a dll file involved in all examples and nowhere any download or such for that dll file...
I cannot make anything out of the examples, something is clearly missing here.

Back again...
It seems like an important thing to mention to a user is that simpleipc is a unit that is part of Fpc itself!

I was looking for a download of it for example on the Github link but found none...

Here it is on my installation:
C:\Programs\Lazarus_2.2.4\fpc\3.2.2\source\packages\fcl-process\src\simpleipc.pp

So it is now probably a matter of looking at how it has been used in some examples.
I want to be able to send a message consisting of an action verb and some argument and expect a return string with some structured content.
So the server needs to be able to do this in Delphi7 (my first check) because there I have the connection working towards the protection dongle.
So I need to copy the file over to delphi if that is possible.
Or else as shown in the github link make a dll that can be used by Delphi7 to use as a server. THat dll needs to be a 32 bit Windows dll otherwise it cannot be used in Delphi7 program.

The client application that will call the server is a port to FreePascal of a Delphi program so it is 64 bit compiled.

Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: Zvoni on March 30, 2023, 03:25:03 pm
Well,
I tried to look at the Github link to get hold of any useful files but after going back and forth I get nowhere...
I simply do not understand how I could use any of this since there seems to be a dll file involved in all examples and nowhere any download or such for that dll file...
I cannot make anything out of the examples, something is clearly missing here.
Look inside this file: https://github.com/z505/SimpleIPC-lib/blob/master/dynsimpleipc.lpr
It's a Library!
If you open this project, and compile it you get the mentioned dll/so!!

And in this folder: https://github.com/z505/SimpleIPC-lib/tree/master/demo-lazarus
the second file is the mentioned dll, though probably compiled with Lazarus.
and in the delphi-folder https://github.com/z505/SimpleIPC-lib/tree/master/demo-delphi-console/Win32/Debug
there is only one file....have a guess which one...
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 30, 2023, 05:21:39 pm
Thanks for explaining!
Now I did this:
+ Retrieved the GitHub content using the green "Code" button and selected to get a zipfile.
+ After expansion I opened the dynsimpleipc project in my Lazarus 2.2.4 on Windows10 x64
+ Now tested the Run/QuickCompile command but it ends in an error.
+ Then tested the Run/Compile command and it finishes green!
+ Going back to the Run/QuickCompile command it finishes green!
+ Finally tested Run/Build but that again ends in an error that will not go away:

Code: Pascal  [Select][+][-]
  1. Compile Project, Target: demo-lazarus\x86_64-win64\dynsimpleipc.dll: Exit code 1, Errors: 1, Hints: 1
  2. ipcparsemsg.pas(41,25) Hint: Parameter "s" not used
  3. Error: Compilation raised exception internally

I have then changed the Project_Options/Paths/Target file name to these:
Code: Pascal  [Select][+][-]
  1. demo-lazarus\$(TargetCPU)-$(TargetOS)\dynsimpleipc32
  2. and
  3. demo-lazarus\$(TargetCPU)-$(TargetOS)\dynsimpleipc64
  4.  
for the two targets in order to build both a 64 bit and a 32 bit version of the dll.
The 64 is when I set Target to Win64 and 32 when I use Target Win32

There seems to be some kind of interaction between the Build/Compile/QuickCompile commands and however I sequence these one of them always produces this error.

Wonder why it happens?

But anyway the dll files are created both of them.

Next is to provide my existing Delphi7 test application with a server implemented using the dll just built.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 30, 2023, 09:05:25 pm
So I have now used Lazarus 2.2.4/Fpc 3.2.2 to compile the demolazarus samples.
I have named the dll dynsimpleipc64.dll and changed the name in the dynsimpleipcwrap.pas file accordingly.
I have compiled the ipcserver.exe and ipcclient.exe apps with no errors shown.

At this point I can start the client but not the server, the server shows a nondescript error 0xc000007b.
(See attached screenshot)
I have tried to set a break-point on the first line in the ipcserver.lpr file (which I assume is where the application starts running) but it does not stop there when I start it inside the Lazarus IDE, just shows what is shown in the screenshot.

The only modifications I have done is to name the output dll file with 64 added after the original name.

OTOH the client starts up just fine, but when I test the button to send a string an error is shown (see attached screenshot)

I can understand the client error because it does find that there is no server running...
Since both applications presumably use the same dll the client response indicates to me that the dll is actually working.
So how can I find the cause of this server error???

EDIT:
For some reason only one screenshot made it into my posting (the last one I added), somethiong is not working OK on this forum...
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 30, 2023, 09:08:21 pm
Adding the first screenshot here...
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 30, 2023, 09:15:40 pm
And finally added a dummy variable I could inc() in FormCreate so I could set a breakpoint there.
The result when starting from within Lazarus (green arrow) is shown here...
Not stopping at the breakpoint..
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 31, 2023, 05:10:10 pm
Any idea why the demo project from github cannot be used?
I have tried so many different tests now and it comes down to the same thing, the server application can be compiled successfully but not built, which is weird to me.
Further after it has been compiled and I start it by doubleclicking the exe file in Windows Explorer it immediately exits with the error code shown above!

Today I reverted the project for creating the dll to the original so it creates a dll named without the 32 or 64 at the end of the name.
With this dll in place and by building the server after modifying the dll reference name in unit dynsimpleipcwrap as follows:
Code: Pascal  [Select][+][-]
  1. const dll = 'dynsimpleipc.dll';
I compiled a new server executable.

Same-same! It again immediately errors out with the same code as shown before ($C000007B).

It seems like this is also a showstopper for me. :(

Notice that the client application using the same dll does not have this problem, it just exits because it cannot find any server to communicate with when I hit the button...
But before that it shows up so I am able to interact with it.
The server app just dies....

What is REALLY the problem here?
I am on a Windows 10 x64 HP high-end laptop and use Lazarus 2.2.4 with FPC 3.2.2.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: Remy Lebeau on March 31, 2023, 05:41:34 pm
There is an SDK to interface with the driver they provide, and it works in Delphi7.
But when I try to port even the simplest application from D7 to Fpc it won't build because the SDK provides an obj file that implements all the API calls into the driver and the obj file generates an error when linking...

It is unusual for an SDK to provide only obj files, since those tend to be compiler-specific.  Most SDKs provide DLLs so that they can be used different compilers.

That being said, since the objs are usable in your Delphi, I would suggest creating your own DLL in Delphi that uses the objs internally, and then use that DLL in FreePascal.

I noticed that both of the sample applications were GUI style apps, is that a requirement for them to work?
I mean do they utilize the Windows message handler that requires a window to talk to?

The server in this case should not be visible (the Delphi7 app) while the client does have a visible form.

You don't need a visual Form in order to use a window.  A window can be hidden, for instance like TApplication's window, or Delphi's AllocationHWnd() function.

WM_COPYDATA
I dont think that sharing data between 32 and 64 bit works due different LPARAM sizes... but havent tested.

There is no problem with that.  WM_COPYDATA's data gets marshaled across process boundaries, and LPARAM handling is local to each process, so a 32bit process can freely send data to a 64bit process and vice versa.  When sending, WM_COPYDATA takes in an LPARAM pointing to memory which is local to the sender, then the data gets marshaled to the other process, and the receiver gets an LPARAM pointing to memory which is local to the receiver.  So LPARAM being different sizes is not a factor at all.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: KodeZwerg on March 31, 2023, 06:55:27 pm
WM_COPYDATA
I dont think that sharing data between 32 and 64 bit works due different LPARAM sizes... but havent tested.

There is no problem with that.  WM_COPYDATA's data gets marshaled across process boundaries, and LPARAM handling is local to each process, so a 32bit process can freely send data to a 64bit process and vice versa.  When sending, WM_COPYDATA takes in an LPARAM pointing to memory which is local to the sender, then the data gets marshaled to the other process, and the receiver gets an LPARAM pointing to memory which is local to the receiver.  So LPARAM being different sizes is not a factor at all.
Thank you for that information, what I right now can confirm is that I am able to send from 64bit to 32bit but not from 32bit to 64bit.
(32bit built with Delphi, 64bit built with FreePascal/Lazarus)
I hope you have a little time to download my attachment and take a look on to help me figure out what I am doing wrong.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: Remy Lebeau on March 31, 2023, 07:25:16 pm
Thank you for that information, what I right now can confirm is that I am able to send from 64bit to 32bit but not from 32bit to 64bit.
(32bit built with Delphi, 64bit built with FreePascal/Lazarus)
I hope you have a little time to download my attachment and take a look on to help me figure out what I am doing wrong.

You are not reporting if FindWindow() fails to locate the window, or even which window it does find.  I would suggest having each app display its Self.Handle in its respective UI, as well as which HWND is being sent to, so you can make sure that FindWindow() is returning the HWND you are expecting.

Or, maybe just get rid of FindWindow() altogether and let the user (ie, you) type in the target HWND directly, ie as a TEdit text that gets converted to an HWND.

Also, you are not checking the return value of SendMessage() for failure at all, either.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: KodeZwerg on March 31, 2023, 08:03:55 pm
Now I do print more it results to find target is okay but nothing happen on 64bit.
Code: Pascal  [Select][+][-]
  1. procedure TfrmMain.btnSendClick(Sender: TObject);
  2. var
  3.   h: THandle;
  4.   cd: TCopyDataStruct;
  5.   rec: TRecToPass;
  6.   res: LRESULT;
  7.   err: DWORD;
  8. begin
  9.   Memo1.Lines.Add('');
  10.   Memo1.Lines.Add('Application Handle: ' + IntToStr(Application.Handle));
  11.   Memo1.Lines.Add('Window Handle: ' + IntToStr(Self.Handle));
  12.   Memo1.Lines.Add('');
  13.   h := FindWindow(nil, 'Demo64');
  14.   if ((h = 0) or (h = INVALID_HANDLE_VALUE)) then
  15.     Exit;
  16.   Memo1.Lines.Add('Found Handle: ' + IntToStr(h));
  17.   Memo1.Lines.Add('');
  18.   rec.s := Self.Edit1.Text;
  19.   rec.i := Random(High(DWORD));
  20.   Self.Label2.Caption := IntToStr(rec.i);
  21.   cd.cbData := SizeOf(rec);
  22.   cd.dwData := rec.i;
  23.   cd.lpData := @rec;
  24.   res := SendMessage(h, WM_COPYDATA, WPARAM(Self.Handle), LPARAM(@cd));
  25.   err := GetLastError;
  26.   Memo1.Lines.Add('Res: ' + IntToStr(Res));
  27.   Memo1.Lines.Add('GetLastError: ' + IntToStr(err));
  28. end;
But maybe I do misunderstand something so I ask for help  :-*
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on March 31, 2023, 09:50:19 pm
It is unusual for an SDK to provide only obj files, since those tend to be compiler-specific.  Most SDKs provide DLLs so that they can be used different compilers.

That being said, since the objs are usable in your Delphi, I would suggest creating your own DLL in Delphi that uses the objs internally, and then use that DLL in FreePascal.
Hi Remy, long time no see!
I have retired from my day work now and only have older versions of Delphi available for moonlighting...
So I have switched altogether to Lazarus/Fpc for my hobby projects.

I thought about dll earlier but then realized that Delphi7 or Delphi2007 (which I still have on my PC) are 32 bit Delphi's and so generate a 32 bit dll, which cannot be loaded by a 64 bit application made by FreePascal...

That is why I asked here and was steered into IPC by a response further up.
But I have not had any luck with the GitHub project, I cannot compile the lazarus-demo fully (server app won't start) and the delphi-demo is done for a more recent delphi than what I have.

It would be possible to use TCP/IP sockets through Indy (available on all my platforms) instead but it seems like doing networking for two apps on the same machine to talk to each other is overkill...
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: Remy Lebeau on March 31, 2023, 10:14:12 pm
Now I do print more it results to find target is okay but nothing happen on 64bit.

This is a known issue in FreePascal/Lazarus (oh yeah, now I remember this.  I did know this once, but forgot about it):

SendMessage WM_COPYDATA is not recognized by Program (https://forum.lazarus.freepascal.org/index.php?topic=3973.0)

SengMessage WM_COPYDATA . Target doesn't receive anything (https://forum.lazarus.freepascal.org/index.php?topic=21354.0)

Basically, the LCL does not dispatch WM_COPYDATA for the Form class to receive, like Delphi's VCL does. So, the solution is to manually subclass the Form's window directly, using the Win32 API SetWindowLong/Ptr() (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlongptra) or SetWindowSubclass() (https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-setwindowsubclass) function, per MSDN: Subclassing Controls (https://learn.microsoft.com/en-us/windows/win32/controls/subclassing-overview).

This is also documented in the Lazarus Wiki:
Processing non-user messages in your window (https://wiki.lazarus.freepascal.org/Win32/64_Interface#Processing_non-user_messages_in_your_window[/url).

The 2nd forum link above has code to demonstrate how to do this.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: jamie on March 31, 2023, 10:59:58 pm
attached is a test app where I made a Unit that can add messages to the loop so you can implement the message handler in the class.

Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: KodeZwerg on March 31, 2023, 11:11:59 pm
Now I do print more it results to find target is okay but nothing happen on 64bit.

This is a known issue in FreePascal/Lazarus (oh yeah, now I remember this.  I did know this once, but forgot about it):

SendMessage WM_COPYDATA is not recognized by Program (https://forum.lazarus.freepascal.org/index.php?topic=3973.0)

SengMessage WM_COPYDATA . Target doesn't receive anything (https://forum.lazarus.freepascal.org/index.php?topic=21354.0)

The solution is to manually subclass the receiving window, using the Win32 API SetWindowLong/Ptr() (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlongptra) or SetWindowSubclass() (https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-setwindowsubclass) function, per MSDN: Subclassing Controls (https://learn.microsoft.com/en-us/windows/win32/controls/subclassing-overview).  This is also documented in the Lazarus Wiki: Processing non-user messages in your window (https://wiki.lazarus.freepascal.org/Win32/64_Interface#Processing_non-user_messages_in_your_window[/url). The 2nd forum link above has code to demonstrate how to do this.
:D :D :D and I thought I am somewhere doing wrong, I've now read more about that scenario here (https://lazarus.lazarus.freepascal.narkive.com/cqwl5U2z/patch-for-processing-wm-copydata-in-win32-bugid-9210)
Thank you Remy!
I will try later again with custom WndProc but since LCL refuse that message I think WM_COPYDATA is a bad choice than for doing IPC with Lazarus.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: KodeZwerg on April 01, 2023, 12:41:55 am
Okay.... custom WndProc did not worked for me, message again was eaten before it could be processed but subclassing worked good.
Attached a working version between Delphi 32 bit and Lazarus 64 bit.
Replacing FindWindow() is a very good advise, in that release it still uses it but more restricted by using both arguments.
Thank you Remy for your advises!
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: tetrastes on April 01, 2023, 12:48:40 am
Now I do print more it results to find target is okay but nothing happen on 64bit.
But maybe I do misunderstand something so I ask for help  :-*

Read lazarus\examples\messages\readme.txt
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: KodeZwerg on April 01, 2023, 12:57:54 am
Now I do print more it results to find target is okay but nothing happen on 64bit.
But maybe I do misunderstand something so I ask for help  :-*

Read lazarus\examples\messages\readme.txt
How does that readme.txt help while I need to process "WM_COPYDATA = 74;" ?
Quote
Use only messages >= LM_USER
I am happy with the found solution and maybe the OP is happy too?  O:-)
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: tetrastes on April 01, 2023, 01:18:26 am
Now I do print more it results to find target is okay but nothing happen on 64bit.
But maybe I do misunderstand something so I ask for help  :-*

Read lazarus\examples\messages\readme.txt
How does that readme.txt help while I need to process "WM_COPYDATA = 74;" ?
Quote
Use only messages >= LM_USER
I am happy with the found solution and maybe the OP is happy too?  O:-)

It explains why nothing happen on 64bit, but I didn't notice the 3rd page of discussion when I wrote that, so sorry for noise.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: KodeZwerg on April 01, 2023, 01:33:39 am
It explains why nothing happen on 64bit, but I didn't notice the 3rd page of discussion when I wrote that, so sorry for noise.
No no, everything is okay with the bitness, that issue rely on the way the FPC/Lazarus developers decided to support Windows specific messages (they just don't :D)
Your contribution was not helping me but at least somewhere in the Examples is written that only LM_USER+ messages are supported and the rest gets eaten, even that they decided to include the message consts in the Windows unit.
After searching for that kind of issue in combination with FPC/Lazarus I really do not want to start flaming or anything else in that direction.
It is like it is and I am thankful for the help I do get here from the pro's :-*
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: tetrastes on April 01, 2023, 01:47:25 am
It explains why nothing happen on 64bit, but I didn't notice the 3rd page of discussion when I wrote that, so sorry for noise.
No no, everything is okay with the bitness, that issue rely on the way the FPC/Lazarus developers decided to support Windows specific messages (they just don't :D)

I understand this, it is simply quote from your post.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: BosseB on April 01, 2023, 10:30:03 am
Now I do print more it results to find target is okay but nothing happen on 64bit.
But maybe I do misunderstand something so I ask for help  :-*

Read lazarus\examples\messages\readme.txt
How does that readme.txt help while I need to process "WM_COPYDATA = 74;" ?
Quote
Use only messages >= LM_USER
I am happy with the found solution and maybe the OP is happy too?  O:-)
Being the tread creator (OP) I do not see how the project you posted can help me at all...
In what way shall it be used? There is only one program in the zipfile and it is also not Delphi7 compatible, complains about a number of properties in the memo when loaded into Delphi7.
What version of Delphi (32 bit) do you use?

There should be two applications for my use case at least:
- One main Lazarus64 bit GUI application (the client), which needs information from the server.
- One Delphi7 32 bit non-GUI server application (invisible), which waits for incoming requests, reads the request and performs the needed action and then sends back a result.

My use case is:

1) A Lazarus 64 bit application, which needs to read from a USB connected device using a driver from the manufacturer.
But the mfg supplied SDK for Delphi does not work with Lazarus because the interface (an OBJ file) is not a COFF formated obj, which is the only type it seems like the FreePascal linker can read.

2) So I need to use a helper app written for Delphi7, which can read the USB and supply the data to the main Lazarus app.
This app needs to be able to receive commands from the main app on what to read from USB and then read and send back the result.

So there are two apps involved, one Delphi7 32 bit server console app and one Lazarus 64 bit main GUI app.

The discussion in this thread is about getting IPC between them working but the GitHub IPC examples I have been pointed to do not even work with both being Lazarus apps (the server crashes immediately on start).

So NO I am not happy.....   >:(

Do I really have to make a network based server app using an Indy10 socket client/server pair?

---- EDIT -----
I have come to the conclusion that using TCP/IP sockets to communicate between the two apps is probably the better solution after all. At least if I will save myself from pulling my hair out...
I could probably limit the server to only listen on localhost so no external spying will be possible.

Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: alpine on April 01, 2023, 11:51:35 am
*snip*

My use case is:

1) A Lazarus 64 bit application, which needs to read from a USB connected device using a driver from the manufacturer.
But the mfg supplied SDK for Delphi does not work with Lazarus because the interface (an OBJ file) is not a COFF formated obj, which is the only type it seems like the FreePascal linker can read.

2) So I need to use a helper app written for Delphi7, which can read the USB and supply the data to the main Lazarus app.
This app needs to be able to receive commands from the main app on what to read from USB and then read and send back the result.

So there are two apps involved, one Delphi7 32 bit server console app and one Lazarus 64 bit main GUI app.

*snip*
What if you just write a simple console Delphi7 app, give the commands as a parameter and use its console output as the result?
You can even use the TProcess.Input/Output pipe streams for communicating while dealing only with ReadLn/WriteLn into the Delphi program.
https://wiki.freepascal.org/Executing_External_Programs#How_to_redirect_output_with_TProcess
 
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: KodeZwerg on April 01, 2023, 11:54:59 am
There is only one program in the zipfile and it is also not Delphi7 compatible, complains about a number of properties in the memo when loaded into Delphi7.
What version of Delphi (32 bit) do you use?
I just downloaded my own Zip and on my machine it shows me
WM_COPYDATA\Delphi32\Demo32.dpr = That file you need to open in your version of Delphi
WM_COPYDATA\Lazarus64\Demo64.lpi = That file you need to open in your version of Lazarus
So you have two complete project sources for two different Pascal environments.

I did coded by using my oldest available Delphi, Turbo Delphi 2006 and a current version of Lazarus(Trunk)/FreePascal(Stable)

complains about a number of properties in the memo when loaded into Delphi7.
Since you are very detailed I can not help further.

From my side you got two different working IPC concepts with full sources, don't expect more from me.
MemoryMappedFile and WM_COPYDATA and all I see from you is, GitHub IPC DLL errors.

Best wishes!
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: 440bx on April 01, 2023, 02:46:07 pm
Do I really have to make a network based server app using an Indy10 socket client/server pair?

and

---- EDIT -----
I have come to the conclusion that using TCP/IP sockets to communicate between the two apps is probably the better solution after all. At least if I will save myself from pulling my hair out...
I could probably limit the server to only listen on localhost so no external spying will be possible.

I'm probably missing something but...

From your description, you will have a Delphi 7 process that communicates with a USB dongle.  That Delphi 7 process will read/write whatever data is protected by the dongle.  That program needs to provide and receive data from a 64 bit program written in FPC.  All this will take place on the _same_ machine.

If that description is reasonably accurate then implementing the communication between that server and any number of clients is a shoe-in for memory mapped files.  Using TCP/IP to implement such simple IPC is grossly inefficient.

I presume you already know how to write the server using Delphi 7 to read/write data and keep the USB dongle happy.  What left is to create a mechanism for that program to communicate with another (most likely using memory mapped files since that seems quite appropriate in this case) and write the 64 bit program that reads/writes the data.

did I miss something ?
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: alpine on April 01, 2023, 10:05:37 pm
@BosseB
Just to demonstrate how simple (and portable) it can be, consider the following example:

Delphi7 32 bit server console app
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. uses
  4.   SysUtils;
  5.  
  6. procedure ReadProc;
  7. var
  8.   StartAddr, EndAddr, W: Word;
  9. begin
  10.   ReadLn(StartAddr, EndAddr);
  11.   for W := StartAddr to EndAddr - 1 do
  12.     WriteLn(IntToHex({ActualRead(W)}0, 2));
  13.   WriteLn('.');
  14. end;
  15.  
  16. procedure WriteProc;
  17. var
  18.   Addr: Word;
  19.   Value: Byte;
  20. begin
  21.   ReadLn(Addr, Value);
  22.   //if not ActualWrite(Addr, Value) then
  23.   //  WriteLn('?');
  24.   //else
  25.     WriteLn('.');
  26. end;
  27.  
  28. var
  29.   Done: Boolean;
  30.   Cmd: String;
  31. begin
  32.   Done := False;
  33.   repeat
  34.     ReadLn(Cmd);
  35.     if Cmd = 'quit' then
  36.       Done := True
  37.     else if Cmd = 'read' then
  38.       ReadProc
  39.     else if Cmd = 'write' then
  40.       WriteProc
  41.     else
  42.       ;
  43.   until Done;
  44. end.
  45.  

And for Lazarus 64 bit main app:
Code: Pascal  [Select][+][-]
  1. program client;
  2.  
  3. uses
  4.   Classes, SysUtils, Process;
  5.  
  6. var
  7.   Srv: TProcess;
  8.   CRLF: String = LineEnding;
  9.   Cmd: String;
  10.  
  11. function GetCh: Char;
  12. begin
  13.   while Srv.Output.NumBytesAvailable < 1 do ;
  14.   Srv.Output.Read(Result, 1)
  15. end;
  16.  
  17. procedure EatChrs;
  18. begin
  19.   while Srv.Output.NumBytesAvailable > 0 do
  20.     GetCh;
  21. end;
  22.  
  23. procedure quitf;
  24. begin
  25.   Cmd := 'quit' + CRLF;
  26.   Srv.Input.Write(Cmd[1], Length(Cmd));
  27.   while Srv.Active do
  28.     Sleep(10);
  29. end;
  30.  
  31. procedure readf(StartAddr, EndAddr: Word);
  32. var
  33.   C: Char;
  34. begin
  35.   EatChrs;
  36.   Cmd := 'read' + CRLF + IntToStr(StartAddr) + ' ' + IntToStr(EndAddr) + CRLF;
  37.   Srv.Input.Write(Cmd[1], Length(Cmd));
  38.   repeat
  39.     C := GetCh;
  40.     Write(C); // process char instead of write -
  41.     //append it to a string and use e.g. ReadStr() or StrToInt() on CRLF
  42.   until C = '.';
  43. end;
  44.  
  45. function writef(StartAddr: Word; Value: Byte): Boolean;
  46. var
  47.   C: Char;
  48. begin
  49.   EatChrs;
  50.   Cmd := 'write' + CRLF + IntToStr(StartAddr) + ' ' + IntToStr(Value) + CRLF;
  51.   Srv.Input.Write(Cmd[1], Length(Cmd));
  52.   repeat
  53.     C := GetCh; Write(C);
  54.   until C in ['.', '?'];
  55.   Result := C = '.';
  56. end;
  57.  
  58. begin
  59.   Srv := TProcess.Create(Nil);
  60.   try
  61.    Srv.Executable := ExtractFilePath(ParamStr(0)) + 'project1.exe';
  62.    Srv.Options := Srv.Options + [poUsePipes];
  63.    Srv.Execute;
  64.  
  65.    readf(0, 10);
  66.    writef($1000, $AA);
  67.    quitf;
  68.  
  69.   finally
  70.     Srv.Free;
  71.   end;
  72. end.  

As you can see, there is no additional complications regarding bitness, object  formats, socket programming, specific APIs, etc. 

IMO that is the most natural way to do IPC - with pipes.
Title: Re: InterProcessCommunication to a Delphi7 app from 64 bit Windows app?
Post by: af0815 on April 02, 2023, 08:35:40 am
BTW, you can use for the server and clients the package Snap7. This is a very robust industrial communication system based on a industrial 'Standard' of a large PLC-Supplier and very well documented. You can have a lot of clients, and share information between mixed systems. Not only Delphi and Lazarus. This Package is available on nearly all popular systems and bitness. For the clients you can also use PascalSCADA, which works without a library and is pure pascal (but can not be a server, client only). PascalSCADA is also very robust, but i think the never versions are Lazarus/fpc only.

I know this idea is not mainstream working with sockets or something, but it is very very stable and used normal for industrial enviroments. But only a idea more for discussion..
 
TinyPortal © 2005-2018