Developer Michael L. on the Embarcadero forums has posted up some sample code for executing an app on Mac OSX and interacting with the result in Delphi XE7 Firemonkey. Developer Sebastian Z. also provides a useful function called ExecAndWait() for executing an app, waiting for it to complete, and then reading the result. The goal of Michael’s code was to be able to launch an app on Mac OSX, read in the result, and control the app by sending it response data. The final code in the thread does just that. The code uses both TNSTask and TNSPipe. You can read more about the NSTask object in the Apple documention. You can also read more about the NSPipe object as well in the docs. The TNSPipe object exposes writeData() and availableData() for writing and reading data from a pipe. This code should work for Appmethod as well. Obviously the code is for Mac OSX only and does not support Android, IOS, or Winows. Check out a snippet of the source code below:
private
Task: NSTask;
LPipeInput,
LPipeOutput,
LPipeError: NSPipe;
// ConsoleError,
// ConsoleInput,
ConsoleOutput : NSData;
OutputText: string;
procedure Exec(FileName: PWideChar);
const
kLineFeed = #10;
procedure TMainForm.CheckForDataButtonClick(Sender: TObject);
begin
Assert(Task <> nil, 'Task has not been created.');
ConsoleOutput := LPipeOutput.fileHandleForReading.availableData;
OutputText := StringOf(BytesOf(ConsoleOutput.bytes, ConsoleOutput.length));
// Memo1.Text.Insert(Memo1.Text.Length, OutPutText)
Memo1.Text := OutputText;
end;
procedure TMainForm.Exec(FileName: PWideChar);
begin
Task := TNSTask.Wrap(TNSTask.Wrap(TNSTask.OCClass.alloc).init);
Task.setLaunchPath(StrToNSStr(FileName));
Task.setStandardOutput((LPipeOutput as ILocalObject).GetObjectID);
Task.setStandardError((LPipeError as ILocalObject).GetObjectID);
Task.setStandardInput((LPipeInput as ILocalObject).GetObjectID);
Task.launch;
// Task.waitUntilExit; This child process is supposed to keep running.
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
LPipeInput := TNSPipe.Create;
LPipeOutput := TNSPipe.Create;
LPipeError := TNSPipe.Create;
Task := nil;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
if (Task <> nil)
then
begin
Task.release;
Task := nil;
end;
LPipeInput.release;
LPipeInput := nil;
LPipeOutput.release;
LPipeOutput := nil;
LPipeError.release;
LPipeError := nil;
end;
procedure TMainForm.SendButtonClick(Sender: TObject);
var
a: NSData;
str: NSString;
begin
Str := StrToNSStr(Edit1.Text + kLineFeed);
a := str.dataUsingEncoding(NSUTF8StringEncoding);
LPipeInput.fileHandleForWriting.writeData(a);
end;
procedure TMainForm.RunEngineButtonClick(Sender: TObject);
begin
Exec('/Users/michaelleahy/PAServer/scratch-dir/Mikes Mini Mac/Stockfish/stockfish-5-64');
end;
Head over and check out the full code snippet for reading and writing from and to a command line pipe on Mac OSX in Delphi XE7 Firemonkey.
1 Comment