|
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1215 Wohnort: Ruhrpott
|
Verfasst am: 04.06.2015, 11:23 Titel: Bidirektionale Pipe |
|
|
Hallo allerseits!
Ob man diese kleine Bibliothek wirklich als "Projekt" bezeichnen kann, weiß ich nicht, aber ich versuche es mal.
Inspiriert worden dazu bin ich von diesem Beitrag, wobei mich allerdings gestört hat, daß die Kommunikation jeweils nur in eine Richtung möglich ist. Im Umfeld von popen() habe ich nichts passendes gefunden, also bin ich selber tätig geworden.
Jetzt wäre es noch schön, wenn die Bibliothek plattformunabhängig einsetzbar wäre, aber bei Linux muß ich leider passen. Wenn sich also ein Linuxer bereitfinden würde, das zu übernehmen: Frisch ans Werk!
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
Roland Chastain
Anmeldungsdatum: 05.12.2011 Beiträge: 192 Wohnort: Frankreich
|
Verfasst am: 06.06.2015, 07:49 Titel: |
|
|
Hallo grindstone!
Es ist sehr interessant. Wäre es möglisch, ein klein Verwendungsbeispiel zu haben? |
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1215 Wohnort: Ruhrpott
|
Verfasst am: 07.06.2015, 01:38 Titel: |
|
|
Hallo Roland Chastain!
Na klar. Hier sind die Programme, mit denen ich die Pipe während der Entwicklung getestet habe (die Programmpfade mußt du natürlich entsprechend anpassen):
bipipeempf Code: | Dim As String g
Print "Hier Empfänger 1"
Print Command(0); " OK"
Print
Do
Input g
Print "ECHO 1>"; g
Loop
| bipipeempf2 Code: | Dim As String g
Print "Hier Empfänger 2"
Print
Do
Input g
Print "ECHO 2>"; g
Loop
| pipetest Code: | #Include "d:\basic\freebasic\tests\bipipe\bipipe.bi"
Dim As String g, zeitvor, cmd
cmd = "d:\basic\freebasic\kurvendiskussion\kudi.exe -1 2 3 4 /1 /2 /3"
Dim As Any Ptr kd = bipOpen(cmd)
Sleep 10000
bipClose(kd)
cmd = "d:\basic\freebasic\tests\bipipe\bipipeempf.exe"
Dim As Any Ptr be1 = bipOpen(cmd,SW_HIDE)
cmd = "d:\basic\freebasic\tests\bipipe\bipipeempf2.exe"
Dim As Any Ptr be2 = bipOpen(cmd,SW_HIDE)
? bipRead(be1);"< Programm 1"
? bipRead(be2);"< Programm 2"
bipWrite(be1,"irgendwas")
bipWrite(be2,"nochmal")
? bipRead(be1);"< Programm 1"
? bipRead(be2);"< Programm 2"
bipWrite(be1,"was ****** anderes","b")
bipWrite(be2,"nochmal ########## was")
? bipRead(be1);"< Programm 1"
? bipRead(be2);"< Programm 2"
? bipRead(be1);"< Programm 1"
? bipRead(be2);"< Programm 2"
Dim As Double zeitmerken = Timer
Do
If Time <> zeitvor Then
? Time;" ";
bipWrite(be1,Time)
bipWrite(be2,Time)
g = bipRead(be1) + "<"
? g;"#"
g = bipRead(be2)
? g
zeitvor = Time
EndIf
Loop Until Timer > zeitmerken + 10
? bipWrite(be1,"+" + Chr(10))
? bipRead(be1)
bipClose(be1)
bipClose(be2)
?
? be1
? be2
?
?"ok"
Sleep
|
"kudi" findest du hier.
Wenn du ffmpeg installiert hast, kannst du auch noch meine Umsetzung des Echtzeitencoders ausprobieren: Code: | #Include "d:\basic\freebasic\tests\bipipe\bipipe.bi"
Dim As Integer n, k
Dim As String ffm,g
Dim As Double timerem
ffm = "c:\programme\audio\ffmpeg\bin\ffmpeg " _
"-f rawvideo " _
"-pix_fmt rgb0 " _
"-s 320x240 " _
"-r 24.000 " _
"-i - " _
"-an " _
"-f avi " _
"-vcodec:v copy " _
"-pix_fmt yuv420p " _
"-profile:v high " _
"-level:v 5.2 " _
"-q:v 0 " _
"-r 24.000 " _
"-y e:\test.avi" 'ausgabefile
Dim As Any Ptr ffmpg = bipOpen(ffm,SW_HIDE)
g = String(307201,Chr(0))
For k = 0 To 240
timerem = Timer + 1/24
For n = 0 To Len(g) - 1 '1 frame mit rauschen erzeugen
g[n] = Int(Rnd * 256)
Next
bipWrite(ffmpg, g, "b") 'frame zu ffmpeg schicken
Print bipRead(ffmpg,1); 'ausgabe von ffmpeg lesen und ausdrucken
Do While Timer < timerem
'auf das ende 1/24 sekunde warten
Loop
Next
Print
Print "OK"
bipClose(ffmpg)
Sleep |
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
Roland Chastain
Anmeldungsdatum: 05.12.2011 Beiträge: 192 Wohnort: Frankreich
|
Verfasst am: 08.06.2015, 18:46 Titel: |
|
|
Vielen Dank, grindstone. Das Beispiel funktioniert perfekt.
Ich wollte etwas mit einem UCI Schach Engine versuchen. Es funktioniert nicht. Was ist falsch in meinen Code?
Code: | ' chessenginetest.bas
#include "vbcompat.bi"
#include "bipipe.bi"
dim cmd as string = "c:\echecs\pharaon\pharaon.exe"
' http://www.fzibi.com/pharaon.htm
? FileExists(cmd)
dim as any ptr pharaon = bipOpen(cmd, SW_HIDE)
? bipRead(pharaon)
bipWrite(pharaon, "uci")
? bipRead(pharaon)
bipClose(pharaon)
sleep |
|
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1215 Wohnort: Ruhrpott
|
Verfasst am: 09.06.2015, 02:35 Titel: |
|
|
Hallo Roland!
Bist du sicher, daß der Pfad richtig ist? Soweit ich weiß heißt dein Projekt "eschecs" und nicht "echecs". Außerdem braucht die Engine nach dem Schreibbefehl eventuell einige Zeit, um zu antworten.
Desweiteren habe ich noch einen kleinen Fehler in der bipRead - Routine korrigiert und die neue Version hochgeladen.
So müsste es jetzt funktionieren: Code: | ' chessenginetest.bas
#Include "vbcompat.bi"
#Include "bipipe.bi"
Dim As String buffer, cmd = "c:\eschecs\pharaon\pharaon.exe"
? FileExists(cmd)
Dim As Any Ptr pharaon = bipOpen(cmd, SW_HIDE)
Sleep 100
? bipRead(pharaon)
? "***********************************"
bipWrite(pharaon, "uci" + Chr(10),"b")
Do
buffer = bipRead(pharaon)
? buffer;
Loop Until InStr(buffer,"uciok")
bipClose(pharaon)
Sleep |
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
Roland Chastain
Anmeldungsdatum: 05.12.2011 Beiträge: 192 Wohnort: Frankreich
|
Verfasst am: 09.06.2015, 09:35 Titel: |
|
|
Vielen Dank für deine Antwort und für das Beispiel. Es funktioniert sehr gut. |
|
Nach oben |
|
|
darkinsanity aka sts
Anmeldungsdatum: 01.11.2006 Beiträge: 456
|
Verfasst am: 29.06.2015, 04:41 Titel: |
|
|
Vor einiger Zeit hab ich mal an etwas gearbeitet, wofür ich auch eine bidirektionale Pipe brauchte. Daher hab ich mir erlaubt, ein bisschen an deinem Code zu basteln:
1. Dein Code basiert ja schon auf der Idee von Objekten, benutzt aber nicht die Möglichkeiten von FreeBASIC dafür, weshalb das Ganze so auch leider nicht typsicher ist. Ich hab den Code mal auf OOP umgebaut, inklusive Konstruktor und Destruktor.
2. In bipWrite hängst du, falls gewünscht, automatisch in CrLf an. Das sollte meiner Meinung nach Sache des Programmes sein welches die Pipe benutzt, nicht der Pipe selbst, daher hab ich das rausgenommen.
3. Linux-Support (basierend auf meinem alten Code) ist jetzt vorhanden, außer für readLine, da hatte ich dann doch keine Lust mehr. Ist bisher auch nicht besonders schön, aber es scheint zu funktionieren. Sicherlich verbesserungswürdig.
4. Da SW_HIDE unter Linux nicht verfügbar ist, hab ich die Option rausgenommen und für Windows als Standard angenommen.
Ich hätte auch noch ein paar Anmerkungen:
- Die WTFPL ist leider keine wirklich anerkannte Lizenz. Die CC0 wäre wohl besser geeignet.
- Die Sache mit dem Timeout wäre wohl in einer erbenden Klasse besser aufgehoben, in der Standard-Implementation will man das möglicherweise nicht drinhaben.
- Die Kindprozesse werden scheinbar nicht gekillt wenn das Programm beendet wird, das sollte vielleicht als Option eingebaut werden.
Den Code gibts auf pastebin:
Testcode
BiPipe-Code _________________ Traue keinem Computer, den du nicht aus dem Fenster werfen kannst -- Steve Wozniak |
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1215 Wohnort: Ruhrpott
|
Verfasst am: 01.07.2015, 11:36 Titel: |
|
|
Hallo darkinsanity!
Zunächst einmal vielen Dank für deine Linux - Erweiterung . Die Bibliothek als Objekt zu programmieren, ist ein interessanter Ansatz, ich muß allerdings gestehen, daß ich mit OO nicht wirklich vertraut bin (obwohl sich dieser Zustand von Tag zu Tag bessert, man kommt ja heute gar nicht mehr daran vorbei ). Entsprechend habe ich auch nicht verstanden, was an meiner Bibliothek nicht typensicher sein soll. Ist doch alles klar definiert .
Was das angehängte CR/LF betrifft, stimme ich dir zu. Ich hatte mich am PRINT - Befehl orientiert, mußte aber inzwischen auch feststellen, daß das in der Praxis mehr Arbeit macht als es einspart.
Den Wert für wShowWindow fest auf SW_HIDE zu setzen, ist allerdings keine so gute Idee. Zum einen soll nicht jedes gestartete Programm versteckt ausgeführt werden ("kudi" unsichtbar laufen zu lassen, würde beispielsweise nicht sehr viel Sinn machen), zum anderen ist es in der Entwicklungsphase besser, auch Kindprozesse, die eigentlich unsichtbar bleiben sollen, mindestens mit SW_MINIMIZE zu starten, damit sie in der Taskleiste auftauchen und man sie bei Bedarf einfach schließen kann, wenn der Elternprozess abgestürzt ist oder "unfreundlich" beendet werden mußte. Sonst könnte es leicht passieren, daß man irgendwann 20 oder 30 verwaiste Kindprozesse laufen hat, die man nur noch über den Taskmanager abschießen kann.
Was die Lizenz betrifft, finde ich CC0 in Ordnung.
Das automatische Timeout ist notwendig, da bipRead sonst erst zurückkehrt, wenn der Kindprozess mindestens 1 Zeichen in die Pipe geschrieben hat. Wenn das nicht gewünscht wird, kann der Wert mit -1 auf (quasi) unendlich (knapp 50 Tage) gesetzt werden. Wenn das immer noch nicht reichen sollte, kann man den Typ auf ULongInt ändern. Da wird dann unsere Sonne zum roten Riesen, bevor das Timeout abgelaufen ist .
Die Kindprozesse bei einem Absturz/Abschuss des Elternprozesses automatisch zu beenden, sehe ich keine Moglichkeit, außer der Kindprozess ist so programmiert, daß er sich selbst beendet, wenn der Elternprozess weg ist.
Deine Art, die Routinen aufzurufen, ist allerdings etwas unüblich. Ich habe mir darum erlaubt, dein Programm so zu erweitern, daß die ursprünglichen Aufrufe wieder funktionieren:
Bipipe für Win + Linux
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
Jojo alter Rang
Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 01.07.2015, 18:51 Titel: |
|
|
Zitat: | Dim As Any Ptr be1 = bipOpen(cmd,SW_HIDE) |
Das ist schon mal alles andere als typsicher.
Sind alle Operationen nur auf dem relevanten Objekt verfügbar, sind sie typsicher(er). Die Verwendung von Konstruktoren und Destruktoren erlaubt auch die Benutzung des sehr praktischen RAII-Prinzips, um Programmierfehler zu vermeiden. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
|
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1215 Wohnort: Ruhrpott
|
Verfasst am: 02.07.2015, 00:53 Titel: |
|
|
Jojo hat Folgendes geschrieben: |
Zitat:
Dim As Any Ptr be1 = bipOpen(cmd,SW_HIDE)
Das ist schon mal alles andere als typsicher. | Wo genau liegt da das Problem? Wegen "Any"? Lass mich an deiner Weisheit teilhaben, OOP ist für mich ziemliches Neuland.
Ich habe der neuen Bibliothek noch ein Feature (wieder-)hinzugefügt, nämlich daß der Pointer beim Beenden automatisch auf 0 gesetzt wird. Ich würde das eigentlich gerne direkt mit dem Destructor machen, aber da ich diesem keine Parameter übergeben kann, weiß ich nicht, wie das gehen könnte.
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
Jojo alter Rang
Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 02.07.2015, 01:16 Titel: |
|
|
grindstone hat Folgendes geschrieben: | Wo genau liegt da das Problem? Wegen "Any"? Lass mich an deiner Weisheit teilhaben, OOP ist für mich ziemliches Neuland. |
Naja, dass "any" alles andere als typsicher ist, liegt doch praktisch schon im Namen. Bei einem Any-Pointer geht doch jegliche Typinformation verloren! Du könntest darin genau so gut das Ergebnis von ImageCreate speichern und das dann an deine Funktionen übergeben. Sind die Funktionen direkt Memberfunktionen deines State-Objekts, kann das nicht passieren, weil auf einem Bildobjekt kannst du nunmal keine Pipe-Operationen aufrufen, weil sie nur Teil deines Pipe-Objekts sind. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
|
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1215 Wohnort: Ruhrpott
|
Verfasst am: 03.07.2015, 08:44 Titel: |
|
|
Tatsächlich! Code: | Dim As BiPipe Ptr ffm = ImageCreate(100,100) | liefert eine 0 zurück, das Programm merkt also während der Laufzeit, daß man etwas illegales vorhat. Bis jetzt dachte ich, die Typangabe bei Pointern wäre nur wegen der Sprungweite beim Indizieren interessant, ansonsten wäre er nichts weiter als eine Zahl.
Vielen Dank für das Schließen dieser Bildungslücke!
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
St_W
Anmeldungsdatum: 22.07.2007 Beiträge: 949 Wohnort: Austria
|
Verfasst am: 04.07.2015, 13:23 Titel: |
|
|
grindstone hat Folgendes geschrieben: | Tatsächlich! Code: | Dim As BiPipe Ptr ffm = ImageCreate(100,100) | liefert eine 0 zurück, das Programm merkt also während der Laufzeit, daß man etwas illegales vorhat. Bis jetzt dachte ich, die Typangabe bei Pointern wäre nur wegen der Sprungweite beim Indizieren interessant, ansonsten wäre er nichts weiter als eine Zahl.
Vielen Dank für das Schließen dieser Bildungslücke!
Gruß
grindstone |
Darum geht es nicht unbedingt bei Typsicherheit und mich würde es auch sehr stark wundern, wenn die 0 aufgrund der Zuweisung zustande käme. (Vielleicht hast du vor ImageCreate noch keine Screen initialisierung?)
Wenn du den Pointer Typ angibst, kann der Compiler statisch (zur Compile-Zeit) einige Typprüfungen machen. Zur Laufzeit werden wohl bei FB nicht viele Typprüfungen durchgeführt (wenn überhaupt; vielleicht mit -exx). _________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken) |
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1215 Wohnort: Ruhrpott
|
Verfasst am: 04.07.2015, 15:23 Titel: |
|
|
@St_W:
Stimmt, ich hatte vorher keinen Bildschirm geöffnet. Mit Code: | ScreenRes 640,480
Dim As BiPipe Ptr ffm = ImageCreate(100,100)
Print ffm
Sleep | bekomme ich einen Pointer angezeigt, es gibt weder beim Compilieren noch zur Laufzeit eine Fehlermeldung.
Jetzt bin ich genauso schlau wie vorher.
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
Jojo alter Rang
Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 04.07.2015, 21:26 Titel: |
|
|
Gerade jetzt sollte dir doch ein Licht aufgehen - Du gibst an, dass da ein BiPipe-Objekt sei, obwohl es ein Bild ist. Liest du also die Felder des BiPipe-Objektes aus, kriegst du nur Müll! Das kann in diesem Umfang nicht passieren (bzw nur mit sehr viel krimineller Energie) wenn du die Funktionen Teil des Objekts sind. Beispiel:
Code: |
Dim as Any Ptr tollerPointer = new BiPipe(...)
Dim as Any Ptr tolerPointer = ImageCreate(...)
BiPipeFunktion(tolerPointer) 'man beachte den Rechtschreibfehler
|
vs
Code: |
Dim as Any Ptr tollerPointer = new BiPipe(...)
Dim as Any Ptr tolerPointer = ImageCreate(...)
tolerPointer->Funktion() 'kompiliert noch nicht mal, egal ob das ein Any Ptr oder ein Fb.Image Ptr ist.
|
_________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
|
|
Nach oben |
|
|
nemored
Anmeldungsdatum: 22.02.2007 Beiträge: 4603 Wohnort: ~/
|
Verfasst am: 04.07.2015, 22:42 Titel: |
|
|
Wenn alle Pointertypen korrekt deklariert sind und auf ANY PTR komplett verzichtet wird, bekommst du natürlich auch Sicherheit hinein.
Code: | #INCLUDE ONCE "fbgfx.bi"
SUB test(zeiger AS INTEGER PTR)
' tue was
END SUB
DIM ptr1 AS INTEGER PTR, ptr2 AS FB.Image PTR
test(ptr2) ' Compilerfehler |
Aber es hindert den Programmierer halt nicht daran, z. B. aus Bequemlichkeit auf ANY PTR zurückzugreifen und dann versehentlich was falsches zu übergeben. Wenn die Funktion dagegen eine Methode deines UDTs ist, kann er nur etwas falsches übergeben, wenn er ganz bewusst falsch castet. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1215 Wohnort: Ruhrpott
|
Verfasst am: 05.07.2015, 12:15 Titel: |
|
|
Ok, das habe ich jetzt verstanden, vielen Dank dafür.
Aber ich habe bis jetzt noch in keinem Tutorial oder Programmbeispiel gesehen, daß auf die Funktionen einer Bibliothek mithilfe des Pfeiloperators zugegriffen wird. Sind die Bibliotheken alle nicht OO, geschieht das intern oder kommt das noch?
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
Jojo alter Rang
Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 05.07.2015, 12:36 Titel: |
|
|
Bei den meisten Bibliotheken, die man in FreeBASIC so verwendet, handelt es sich bei den Headern meist um direktübersetzungen der C-Header. C ist keine objektorientierte Programmiersprache, hat aber halt den Vorteil, dass fast jeder Compiler die Calling Conventions von C umsetzt und somit die C-Header leicht übersetzt werden können. Der Aufruf von Objektfunktionen (thiscall) ist nicht standardisiert* und verschiedene Compiler setzen diese verschieden um, sodass man bei C++-Bibliotheken für jeden Compiler eine eigene vorkompilierte Version benötigt (oder man kompiliert die Bibliothek gleich selbst, was auch nicht weiter schwer ist).
Für viele Bibliotheken werden oft auch OO-Wrapper um die C-Version drumherum gepackt, die die C-Funktionen in Objekte der Zielsprache einbetten, um eben die Vorteile von OO nutzen zu können. Bei C++ ist das oft verbreitet (für viele C-Bibliotheken gibt es direkt mitegelieferte oder auf der Projektseite angebotene C++-Wrapper, z.B. bei lua oder sqlite), bei FB vmtl mangels Engagement eher weniger.
* das gilt prinzipiell auch für alle Calling Conventions in C, aber diese sind zwischen den Compilern wesentlich standardisierter, weil eben klassischerweise die Betriebssystem-API in C verfasst ist und man ja irgendwie darauf zugreifen können muss. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
|
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|