* * *

Author Topic: [SOLVED] TProcess with Octave 4.2 On Win32  (Read 742 times)

trayres

  • Jr. Member
  • **
  • Posts: 69
[SOLVED] TProcess with Octave 4.2 On Win32
« on: February 13, 2017, 08:38:35 am »
Has anyone tried this recently with Octave 4.2 on Win32?

There is a thread from 2009 on this located here:
http://forum.lazarus.freepascal.org/index.php?topic=6693.0

Question XPosted to SO here:
http://stackoverflow.com/questions/42214845/interfacing-octave-and-lazarus-freepascal-with-tprocess

If I use the octave-cli.exe, I get the TProcess.Running property to be True, but I'm unable to grab bytes from it.

It looks like the octave.vbs script calls octave-gui.exe within /bin, then passes --no-gui and 1 to it; I'm not quite sure what's going on.

Code below, primitive  project as attachment!

Code: Pascal  [Select]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Process;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Button2: TButton;
  17.     procedure Button1Click(Sender: TObject);
  18.     procedure Button2Click(Sender: TObject);
  19.   private
  20.     { private declarations }
  21.   public
  22.     { public declarations }
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.   POctave: TProcess;
  28.  
  29. implementation
  30.  
  31. {$R *.lfm}
  32.  
  33. { TForm1 }
  34.  
  35. procedure TForm1.Button1Click(Sender: TObject);
  36. begin
  37.   if (not POctave.Running) then
  38.   begin
  39.     POctave.Executable := 'C:\Octave\Octave-4.2.0\bin\octave-cli.exe';
  40.     POctave.Parameters.Add('--no-gui');
  41.     POctave.Options := [poUsePipes];
  42.     WriteLn('-- Executing octave --');
  43.     POctave.Execute;
  44.   end;
  45.  
  46. end;
  47.  
  48. procedure TForm1.Button2Click(Sender: TObject);
  49. var
  50.   command: string;
  51.   Buffer: string;
  52.   BytesAvailable: DWord;
  53.   BytesRead: longint;
  54.   NoMoreOutput: boolean;
  55. begin
  56.   command := 'pwd' + #10;
  57.   if (POctave.Running) then
  58.     POctave.Input.Write(command, Length(command));
  59.  
  60.   if (POctave.Running) then
  61.   begin
  62.     BytesAvailable := POctave.Output.NumBytesAvailable;
  63.     BytesRead := 0;
  64.     while BytesAvailable > 0 do
  65.     begin
  66.       SetLength(Buffer, BytesAvailable);
  67.       BytesRead := POctave.OutPut.Read(Buffer[1], BytesAvailable);
  68.       WriteLn(Buffer);
  69.       BytesAvailable := POctave.Output.NumBytesAvailable;
  70.       NoMoreOutput := False;
  71.     end;
  72.   end;
  73. end;
  74.  
  75. initialization
  76.   POctave := TProcess.Create(nil);
  77.  
  78. finalization
  79.   POctave.Free;
  80.  
  81. end.
« Last Edit: February 14, 2017, 01:10:52 pm by trayres »

Cyrax

  • Sr. Member
  • ****
  • Posts: 498
Re: TProcess with Octave 4.2 On Win32
« Reply #1 on: February 13, 2017, 01:07:33 pm »
Add Sleep(10); clause before you check TProcess.Output.NumBytesAvailable. OS/the process needs some time to fill up the pipe(s). After the process has done its execution, check again if there is something left in the pipe(s).
« Last Edit: February 13, 2017, 01:09:07 pm by Cyrax »

trayres

  • Jr. Member
  • **
  • Posts: 69
Re: TProcess with Octave 4.2 On Win32
« Reply #2 on: February 13, 2017, 06:38:53 pm »
I added Sleep(10):

Code: Pascal  [Select]
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. var
  3.   command: string;
  4.   Buffer: string;
  5.   BytesAvailable: DWord;
  6.   BytesRead: longint;
  7.   NoMoreOutput: boolean;
  8. begin
  9.   command := 'pwd' + #10;
  10.   if (POctave.Running) then
  11.     POctave.Input.Write(command, Length(command));
  12.  
  13.   Sleep(10);
  14.   if (POctave.Running) then
  15.   begin
  16.     BytesAvailable := POctave.Output.NumBytesAvailable;
  17.     BytesRead := 0;
  18.     while BytesAvailable > 0 do
  19.     begin
  20.       SetLength(Buffer, BytesAvailable);
  21.       BytesRead := POctave.OutPut.Read(Buffer[1], BytesAvailable);
  22.       WriteLn(Buffer);
  23.       BytesAvailable := POctave.Output.NumBytesAvailable;
  24.       NoMoreOutput := False;
  25.     end;
  26.   end;
  27. end;

I'm still not seeing anything in the buffer  :(

I also tried @LeLeDumbo's OctaveGUI with 4.2 and wasn't able to get it to work. 
« Last Edit: February 13, 2017, 08:51:19 pm by trayres »

Cyrax

  • Sr. Member
  • ****
  • Posts: 498
Re: TProcess with Octave 4.2 On Win32
« Reply #3 on: February 13, 2017, 09:00:25 pm »
Add Sleep inside the while loop, too.

trayres

  • Jr. Member
  • **
  • Posts: 69
Re: TProcess with Octave 4.2 On Win32
« Reply #4 on: February 13, 2017, 09:09:26 pm »
Add Sleep inside the while loop, too.

Added it per recommendation; still no joy :(

Code: Pascal  [Select]
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. var
  3.   command: string;
  4.   Buffer: string;
  5.   BytesAvailable: DWord;
  6.   BytesRead: longint;
  7.   NoMoreOutput: boolean;
  8. begin
  9.   command := 'pwd'; // + #10;
  10.   if (POctave.Running) then
  11.     POctave.Input.Write(command, Length(command));
  12.  
  13.   Sleep(50);
  14.   if (POctave.Running) then
  15.   begin
  16.     Sleep(50);
  17.     BytesAvailable := POctave.Output.NumBytesAvailable;
  18.     BytesRead := 0;
  19.     while BytesAvailable > 0 do
  20.     begin
  21.       SetLength(Buffer, BytesAvailable);
  22.       BytesRead := POctave.OutPut.Read(Buffer[1], BytesAvailable);
  23.       WriteLn(Buffer);
  24.       BytesAvailable := POctave.Output.NumBytesAvailable;
  25.       Sleep(10);
  26.       NoMoreOutput := False;
  27.     end;
  28.   end;
  29. end;  

I also just tried changing the Octave command to end with #13#10, just in case it was some kind of platform specific 'return' key silliness:

Code: Pascal  [Select]
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. var
  3.   command: ansistring;
  4.   Buffer: string;
  5.   BytesAvailable: DWord;
  6.   BytesRead: longint;
  7.   NoMoreOutput: boolean;
  8. begin
  9.   command := 'pwd'#13#10;
  10.   if (POctave.Running) then
  11.     POctave.Input.Write(command, Length(command));
  12.   Sleep(100);
  13.  
  14.   if (POctave.Running) then
  15. begin
  16.     Sleep(100);
  17.     BytesAvailable := POctave.Output.NumBytesAvailable;
  18.     BytesRead := 0;
  19.     while BytesAvailable > 0 do
  20.     begin
  21.       Sleep(100);
  22.       SetLength(Buffer, BytesAvailable);
  23.       BytesRead := POctave.OutPut.Read(Buffer[1], BytesAvailable);
  24.       WriteLn(Buffer);
  25.       BytesAvailable := POctave.Output.NumBytesAvailable;
  26.       NoMoreOutput := False;
  27.     end;
  28.   end;
  29. end;  

Still no go. I also tried pointing at octave-gui.exe instead of octave-cli.exe. However! The following solved it (I started from @LeLeDumbo's code and noticed he wasn't calling

Code: Pascal  [Select]
  1. POctave.Input.Write(command, Length(command));
  2.  

He was calling:
Code: Pascal  [Select]
  1. POctave.Input.Write(command[1], Length(command));

The final result:
Code: Pascal  [Select]
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. var
  3.   command: ansistring;
  4.   Buffer: string;
  5.   BytesAvailable: DWord;
  6.   BytesRead: longint;
  7.   NoMoreOutput: boolean;
  8. begin
  9.   command := 'pwd'#10;
  10.   if (POctave.Running) then begin
  11.     WriteLn(command[1]);
  12.     POctave.Input.Write(command[1], Length(command));  //<----command[1] instead of command
  13.   end;
  14.   Sleep(20);
  15.  
  16.   if (POctave.Running) then
  17. begin
  18.     Sleep(20);
  19.     BytesAvailable := POctave.Output.NumBytesAvailable;
  20.     BytesRead := 0;
  21.     while BytesAvailable > 0 do
  22.     begin
  23.       Sleep(20);
  24.       SetLength(Buffer, BytesAvailable);
  25.       BytesRead := POctave.OutPut.Read(Buffer[1], BytesAvailable);
  26.       WriteLn(Buffer);
  27.       BytesAvailable := POctave.Output.NumBytesAvailable;
  28.       NoMoreOutput := False;
  29.     end;
  30.   end;
  31. end;  

Now it runs like a champ!
I did writeln[0] - and remembered something from many, many moons ago:
https://en.wikipedia.org/wiki/Comparison_of_Pascal_and_C#Strings

They're length prefixed. I'm...an idiot.
 :D :D :D
« Last Edit: February 14, 2017, 01:10:26 pm by trayres »

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus