have you forgotten the proc.Execute ? :-X
This is practically what a TTimer does: do its job, let the GUI do its, then waits for some time.
application.ProcessMessages; sleep(200);
The C program is closed, so i cannot even give the source of it. As for the Pascal, as i said, it's not mine, i cannot distribute the sources.You don't have to give the same source code, create yourself one that demonstrates the behavior, as simple as possible.
The external program is running fine, it communicates via serial port and i see the LED blinking. If the programs tops, the LED stops blinking. And it does not matter if i use CommandLine or the new methods, i've checked the parameters and all is fine...
You don't have to give the same source code, create yourself one that demonstrates the behavior, as simple as possible.I already did. It's in the opening post.
In that case, the program might really be running, but buffers its output. Again this is just a guess. One more thing, it could actually be writing to stderr instead of stdout, so you might want to add poStderrToOutPut to Options property.No, it's writing to stdout. I tried poStderrToOutPut, but no avail. I tried to redirect the program's output to a file from console and 1> did the redirect, 2> did not. What do you mean by "it buffers its output"? It's just do a lot of printf.
You don't have to give the same source code, create yourself one that demonstrates the behavior, as simple as possible.I already did. It's in the opening post.
But it contains the essential part and as i already told, i only missed the Execute from this example code; it is in the original.Uncompilable, therefore cannot be used as a base to reproduce the behavior. You first create one that all of us can compile, using your real C executable where it demonstrates the behavior that you said, where the output stream is always empty. You then rename the C executable (in the Pascal code) to whatever you wish, keeping the rest of the code intact. Then post or attach here.
Uncompilable, therefore cannot be used as a base to reproduce the behavior. You first create one that all of us can compile, using your real C executable where it demonstrates the behavior that you said, where the output stream is always empty. You then rename the C executable (in the Pascal code) to whatever you wish, keeping the rest of the code intact. Then post or attach here.Okay, here is the real one:
constructor TEMP860Thread.Create(CreateSuspended : boolean);
begin
inherited Create(CreateSuspended);
Self.Stop := False;
end;
procedure TEMP860Thread.ErrorSet;
begin
set_error_bits(ERROR_CASHHANDLER_DIED);
end;
procedure TEMP860Thread.ErrorClear;
begin
set_error_bits(ERROR_CASHHANDLER_DIED);
end;
procedure TEMP860Thread.CoinDrop;
begin
add_coin(Self.Money);
end;
procedure TEMP860Thread.FinishTransaction;
begin
finish_transaction;
end;
procedure TEMP860Thread.ClearTransaction;
begin
clear_transaction;
end;
procedure TEMP860Thread.Execute;
var
bc, i, a, code, tries: longint;
cs: array[0..3] of string;
begin
while (not Self.Stop) do
begin
{$IFDEF CPUARMHF}
if (not emp860.Running) then
begin
if (emp860_fails < 16) then
begin
emp860.Execute;
writeln('EMP860 executed.');
inc(emp860_fails);
end
else
begin
Synchronize(@ErrorSet);
end;
end
else
begin
writeln('READ');
if (emp860_fails > 15) then
begin
Synchronize(@ErrorClear);
end;
emp860_fails := 0;
bc := 0;
tries := 0;
while ((bc = 0) and (tries < 20)) do
begin
sleep(10);
bc := emp860.Output.NumBytesAvailable;
inc(tries);
end;
writeln('bc = ' + inttostr(bc));
if (bc = 0) then
begin
inc(emp860_nosignal);
if (emp860_nosignal > 15) then
begin
emp860_nosignal := 0;
emp860.Terminate(0);
writeln('EMP860 terminated.');
end;
end
else
begin
emp860.Output.Read(pipe_buffer[0], bc);
emp860_nosignal := 0;
i := 0;
a := 0;
cs[0] := '';
cs[1] := '';
cs[2] := '';
cs[3] := '';
while (i < bc) do
begin
if ((pipe_buffer[i] <> ';') and (pipe_buffer[i] <> #10)) then
begin
cs[a] := cs[a] + pipe_buffer[i];
end
else
begin
if (pipe_buffer[i] = ';') then
begin
inc(a);
end
else
begin
code := strtoint(cs[0]);
if (code = 10) then
begin
Self.Money := strtoint(cs[2]);
Synchronize(@CoinDrop);
end;
if (code = 12) then
begin
Synchronize(@FinishTransaction);
end;
if (code = 13) then
begin
Synchronize(@ClearTransaction);
end;
a := 0;
cs[0] := '';
cs[1] := '';
cs[2] := '';
cs[3] := '';
end;
end;
inc(i);
end;
end;
end;
{$ENDIF}
sleep(100);
WriteLn('EMP860 TICK');
end;
end;
and in the startup:{$IFDEF CPUARMHF}
WriteLn('EMP860 process initialization...');
emp860 := TProcess.Create(nil);
emp860.Options := [poUsePipes, poStderrToOutPut];
emp860.CommandLine := '/usr/local/bin/emp860 /dev/ttyUSB0 ' + generate_bitmask(AcceptableCoins, 6);
emp860_fails := 0;
emp860_nosignal := 0;
{$ENDIF}
WriteLn('Creating EMP860 thread...');
emp860thread := TEMP860Thread.Create(false);
And the declaration: TEMP860Thread = class(TThread)
protected
procedure Execute; override;
procedure ErrorSet;
procedure ErrorClear;
procedure CoinDrop;
procedure FinishTransaction;
procedure ClearTransaction;
public
var Stop: Boolean;
var Money: Word;
Constructor Create(CreateSuspended : boolean);
end;
@TCHLinux on ARMHF, Lazarus is 1.6.4 and FPC is 3.0.2.
What OS/CPU and Laz/FPC version?
Does the example in this post (http://forum.lazarus.freepascal.org/index.php/topic,39535.msg271659.html#msg271659) work for you?
If yes, replace the CommandLine with yours. Does it work?
Your first post shows that the C prog takes two arguments. What type of arguments? Numbers?
hello,Nope, did not work for me.
i have tried my example with the option -i to 200 ms for the ping ( -i = Wait interval seconds between sending each packet ) :
Proc := TProcess.Create(nil); Proc.Options := [poUsePipes]; Proc.Executable := '/bin/ping'; Proc.Parameters.Add('-c 100'); Proc.Parameters.Add('-i 0.2'); Proc.Parameters.Add('127.0.0.1'); Proc.Execute();
it still works with Output every 200 milliseconds on Ubuntu 16.04 64 bits Lazarus 1.8 !
Friendly, J.P
Proc := TProcess.Create(nil); Proc.Options := [poUsePipes]; Proc.Executable := '/bin/ping'; Proc.Parameters.Add('-c 100'); Proc.Parameters.Add('-i 0.2'); Proc.Parameters.Add('127.0.0.1'); Proc.Execute();
If you needed to do that, the C++ written program does not use any known standard regarding IO. Because those are pretty well defined. Let me guess: direct access.... by-passing cout...The C++ program used printf, but now i omitted the console writing, i changed the main function to another which has two additional parameters besides the original (i mean original expected, not the argc/argv, but what arrives in them): one is responsible for allowing the function to continue and the other is a procedure's address. So practically i run the C++ function from Pascal, give them an address of a boolean which i use for halting the cycle and a Pascal procedure's address which handles the arriving result.