Unit Crt WriteLn in Threads bzw. Externe Programme
Unit Crt WriteLn in Threads bzw. Externe Programme
Hallo,
erstmal einen netten Gruß an alle. Ich habe mich angemeldet da ich einiges mit FreePascal Programmiere. Was mir gefällt ist die unabhängikeit von Plattformen. Meistens schreibe ich Unix Programme. Das war es eigentlich schon zu meiner Person.
Nun zu meiner Frage. Ich habe eine Konsolen anwendung geschrieben wo ich auch gerne Farbigen Text ausgeben möchte. Das klappt auch einwandfrei. Ich habe nur ein Problem wenn ich mit WriteLn entweder aus einem Thread oder aus einem anderen Programm was ich mit fpsystem aufrufe Text ausgebe. Der ist immer "schief". Das heisst er macht nur ein LF und kein CR. Dadurch stehen die ausgaben nicht untereinander.
Da ich auch Externe Programme aufrufe die ich nicht geschrieben habe, kann ich es in diesen Programmen nicht ändern. Binde ich Crt nicht ein und verzichte auf Farben ist wieder alles richtig.
System ist Debian.
Was mache ich da falsch?
Vielen dank im Voraus
erstmal einen netten Gruß an alle. Ich habe mich angemeldet da ich einiges mit FreePascal Programmiere. Was mir gefällt ist die unabhängikeit von Plattformen. Meistens schreibe ich Unix Programme. Das war es eigentlich schon zu meiner Person.
Nun zu meiner Frage. Ich habe eine Konsolen anwendung geschrieben wo ich auch gerne Farbigen Text ausgeben möchte. Das klappt auch einwandfrei. Ich habe nur ein Problem wenn ich mit WriteLn entweder aus einem Thread oder aus einem anderen Programm was ich mit fpsystem aufrufe Text ausgebe. Der ist immer "schief". Das heisst er macht nur ein LF und kein CR. Dadurch stehen die ausgaben nicht untereinander.
Da ich auch Externe Programme aufrufe die ich nicht geschrieben habe, kann ich es in diesen Programmen nicht ändern. Binde ich Crt nicht ein und verzichte auf Farben ist wieder alles richtig.
System ist Debian.
Was mache ich da falsch?
Vielen dank im Voraus
-
- Beiträge: 6917
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Unit Crt WriteLn in Threads bzw. Externe Programme
Verstehe ich dich richtig, du schreibst in
deinem Programm mit der Unit Crt. Und gleichzeitig schreibt ein externes in die gleiche Konsole ?

Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
Re: Unit Crt WriteLn in Threads bzw. Externe Programme
Ja, mein Programm ruft unter anderem Externe Programme auf. Und die ausgaben möchte ich natürlich auch sehen. Oder wenn man etwas in einem Thread ausgibt.
-
- Beiträge: 6917
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Unit Crt WriteLn in Threads bzw. Externe Programme
Normalerweise verwendet Unixsystem nur ein LF. Was ich mir in deinem Fall vorstellen kann, das die Unit Crt die Konsole auf CR-LF umstellt.
Versuche mal anstelle von Writeln(blabla) ein Write(blabla, #10).
Versuche mal anstelle von Writeln(blabla) ein Write(blabla, #10).
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 2120
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Unit Crt WriteLn in Threads bzw. Externe Programme
Soweit ich weiß macht die CRT Unit internes buffering (was sonst vom OS übernommen wird) und ich hab grade mal drüber geschaut, sie ist nicht Thread-Safe.
D.h. WriteLn aufrufe aus verschiedenen Threads ohne lock, wenn du die CRT unit benutzt kann ganz schön in die Hose gehen.
Wenn es dir nur um Farben geht, mittlerweile kann selbst der Windows Terminal emulator Escape Codes. Du kannst also ganz einfach sowas bauen:
Für sowas simples wie reiner Farbiger output ist die CRT unit ein bisschen mit kanonen auf spatzen schießen
D.h. WriteLn aufrufe aus verschiedenen Threads ohne lock, wenn du die CRT unit benutzt kann ganz schön in die Hose gehen.
Wenn es dir nur um Farben geht, mittlerweile kann selbst der Windows Terminal emulator Escape Codes. Du kannst also ganz einfach sowas bauen:
Code: Alles auswählen
program Test;
{$Mode ObjFPC}{$H+}
uses
SysUtils;
type
TConsoleColor = (ccBlack = 0, ccRed, ccGreen, ccYellow, ccBlue, ccMagenta, ccCyan, ccWhite);
function Colored(const str: String; color: TConsoleColor): String;
begin
Result := Format(#27'[3%dm%s'#27'[1;49m', [ord(color), str]);
end;
begin
Writeln(Colored('Hello ', ccRed), Colored('World!', ccYellow));
end.
-
- Beiträge: 6917
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Unit Crt WriteLn in Threads bzw. Externe Programme
So nebenbei setzt unter Linux die Unit Crt die Farben auch mit Escape-Sequenzen.
Dieser Code spuckt folgendes aus:
Code: Alles auswählen
procedure TForm1.Button1Click(Sender: TObject);
begin
TextAttr := 4;
WriteLn('Hello World');
TextAttr := 25;
WriteLn('Hello World');
end;
Code: Alles auswählen
[0;1;34;44mHello World
[0;31mHello World
[0;1;34;44mHello World
[0;31mHello World
[0;1;34;44mHello World
[0;31mHello World
[0;1;34;44mHello World
[0;31mHello World
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 2120
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Unit Crt WriteLn in Threads bzw. Externe Programme
Jo, ist auch der "standard" weg unter Unix systemen. Kompliziert wirds erst bei älteren Windows systemen, denn dort werden die Farben über API aufrufe gesetzt, weshabl bis zum neuen Windows 10 Terminal Project (ein Projekt bei dem Microsoft versucht ein benutzbares Terminal in Windows hinzubekommen) es ein echter Krampf war das einzustellen.Mathias hat geschrieben: Fr 29. Mai 2020, 22:03 So nebenbei setzt unter Linux die Unit Crt die Farben auch mit Escape-Sequenzen.
Da Windows 7 mittlerweile von Microsoft allerdings für Tot erklärt wurde, muss man sich nicht mehr die Mühe machen und kann direkt auf die Escape sequenzen gehen, die jetzt überall funktionieren.
Das gesagt, habe ich grade erst gesehen, auf windows muss man bei programm start einmal mit nem API call die escape sequenzen "aktivieren". Hier ist ein C code dazu: https://solarianprogrammer.com/2019/04/ ... terminals/
Code: Alles auswählen
17 void setupConsole(void) {
DWORD outMode = 0;
stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if(stdoutHandle == INVALID_HANDLE_VALUE) {
exit(GetLastError());
}
if(!GetConsoleMode(stdoutHandle, &outMode)) {
exit(GetLastError());
}
outModeInit = outMode;
// Enable ANSI escape codes
outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if(!SetConsoleMode(stdoutHandle, outMode)) {
exit(GetLastError());
}
}
Die CRT Unit macht halt extrem viel und ist ziemlich komplex (modeliert intern den Status des gesammten Terminals um den Cursor zu verfolgen und so späße) und weil sie noch die Oldschool windows API funktionen benutzt für das Terminal zu Setzen (statt ansi escape sequences), ist es damit relativ lahm wenn du sehr viele farbänderungen und so hast. Außerdem durch das eigene Buffern der Unit, verhält sich WriteLn und die Read Funktionen plötzlich anders, und low-level funktionen wie getChar oder so funktionieren gar nicht mehr.
CRT macht vieles einfach (z.b. fenster informationen wie größe, cursor position, etc.), aber kann auch zu sehr speziellen Problemen führen. Daher bin ich der Meinung, wenn man nicht die komplexe funktionalität von CRT braucht und nur einen kleinen teil der Funktionaltiät haben will, ist es meist besser einfach diesen kleinen teil selbst zu bauen.
Schönes beispiel dafür ist auch wenn man eine zeile überschreiben will (z.b. bei nem downloader will man nen progressbar updaten). Das geht mit CRT (hat glaub ich ne funkion clearline oder so), aber es geht viel einfacher so:
Code: Alles auswählen
WriteLn(#13, SomeString);
-
- Beiträge: 6917
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Unit Crt WriteLn in Threads bzw. Externe Programme
Unter dos musste man ansii.sys installieren, ansonsten war nix mit Escape.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
Re: Unit Crt WriteLn in Threads bzw. Externe Programme
Danke für die Tips und Hilfe. Ich werde es probieren.