Ich lerne C ++ und habe gerade angefangen, einige der Funktionen von Qt zum Codieren von GUI-Programmen kennenzulernen. Ich habe mir folgende Frage gestellt:
Wie erhält C ++, das zuvor keine Syntax hatte, die das Betriebssystem nach einem Fenster oder einer Möglichkeit zur Kommunikation über Netzwerke fragen konnte (mit APIs, die ich auch nicht vollständig verstehe, gebe ich zu), plötzlich solche Funktionen durch in C ++ selbst geschriebene Bibliotheken? Es scheint mir alles schrecklich kreisförmig. Welche C ++ - Anweisungen könnten Sie möglicherweise in diesen Bibliotheken finden?
Mir ist klar, dass diese Frage für einen erfahrenen Softwareentwickler trivial erscheint, aber ich habe stundenlang recherchiert, ohne eine direkte Antwort zu finden. Es ist an einem Punkt angelangt, an dem ich dem Tutorial über Qt nicht mehr folgen kann, weil die Existenz von Bibliotheken für mich unverständlich ist.
quelle
Antworten:
Ein Computer ist wie eine Zwiebel, es viele hat viele Schichten, aus dem inneren Kern der reinen Hardware auf die äußerste Anwendungsschicht. Jede Schicht setzt Teile von sich der nächsten äußeren Schicht aus, so dass die äußere Schicht einige der Funktionen der inneren Schichten nutzen kann.
Im Fall von z. B. Windows stellt das Betriebssystem die sogenannte WIN32-API für Anwendungen zur Verfügung, die unter Windows ausgeführt werden. Die Qt-Bibliothek verwendet diese API, um Anwendungen, die Qt verwenden, für ihre eigene API bereitzustellen. Sie verwenden Qt, Qt verwendet WIN32, WIN32 verwendet niedrigere Ebenen des Windows-Betriebssystems usw., bis es elektrische Signale in der Hardware gibt.
quelle
Qt
Hier finden Sie eine Abstraktion der darunter liegenden Ebene, da unter LinuxQt
die Linux-API und nicht die WIN32-API aufgerufen wird.user32.dll
oder möglicherweisegdi32.dll
.Sie haben Recht, dass Bibliotheken im Allgemeinen nichts möglich machen können, was noch nicht möglich ist.
Die Bibliotheken müssen jedoch nicht in C ++ geschrieben sein, um von einem C ++ - Programm verwendet werden zu können. Selbst wenn sie in C ++ geschrieben sind, können sie intern andere Bibliotheken verwenden, die nicht in C ++ geschrieben sind. Die Tatsache, dass C ++ keine Möglichkeit dazu bietet, verhindert nicht, dass es hinzugefügt wird, solange es eine Möglichkeit gibt, dies außerhalb von C ++ zu tun.
Auf einer relativ niedrigen Ebene werden einige von C ++ (oder von C) aufgerufene Funktionen in Assembly geschrieben, und die Assembly enthält die erforderlichen Anweisungen, um alles zu tun, was in C ++ nicht möglich (oder nicht einfach) ist, beispielsweise zum Aufrufen eine Systemfunktion. Zu diesem Zeitpunkt kann dieser Systemaufruf alles tun, was Ihr Computer kann, einfach weil nichts ihn aufhält.
quelle
C und C ++ haben zwei Eigenschaften, die all diese Erweiterbarkeit ermöglichen, von der das OP spricht.
Im Kernel oder in einer Basisplattform im nicht geschützten Modus werden Peripheriegeräte wie die serielle Schnittstelle oder das Festplattenlaufwerk auf die gleiche Weise wie der Arbeitsspeicher der Speicherzuordnung zugeordnet. Der Speicher besteht aus einer Reihe von Schaltern. Durch Umlegen der Schalter des Peripheriegeräts (z. B. eines seriellen Anschlusses oder eines Festplattentreibers) kann Ihr Peripheriegerät nützliche Aufgaben ausführen.
Wenn in einem Betriebssystem im geschützten Modus vom Benutzerbereich aus auf den Kernel zugegriffen werden soll (z. B. beim Schreiben in das Dateisystem oder beim Zeichnen eines Pixels auf dem Bildschirm), muss ein Systemaufruf ausgeführt werden. C hat keine Anweisung zum Ausführen von Systemaufrufen, aber C kann Assembler-Code aufrufen, der den richtigen Systemaufruf auslösen kann. Auf diese Weise kann der C-Code mit dem Kernel kommunizieren.
Um die Programmierung einer bestimmten Plattform zu vereinfachen, werden Systemaufrufe in komplexere Funktionen eingeschlossen, die einige nützliche Funktionen innerhalb des eigenen Programms ausführen können. Es steht einem frei, die Systemaufrufe direkt (mit Assembler) aufzurufen, aber es ist wahrscheinlich einfacher, nur eine der von der Plattform bereitgestellten Wrapper-Funktionen zu verwenden.
Es gibt eine andere API-Ebene, die viel nützlicher ist als ein Systemaufruf. Nehmen Sie zum Beispiel Malloc. Dies ruft nicht nur das System dazu auf, große Speicherblöcke zu erhalten, sondern verwaltet diesen Speicher auch, indem das gesamte Buch über die Vorgänge geführt wird.
Win32-APIs umschließen einige Grafikfunktionen mit einem gemeinsamen Plattform-Widget-Set. Qt geht noch einen Schritt weiter, indem es die Win32- (oder X Windows-) API plattformübergreifend umschließt.
Obwohl ein C-Compiler C-Code in Maschinencode umwandelt und der Computer für die Verwendung von Maschinencode ausgelegt ist, sollten Sie grundsätzlich erwarten, dass C in der Lage ist, die Löwenfreigabe zu erreichen oder was ein Computer tun kann. Alles, was die Wrapper-Bibliotheken tun, ist das schwere Heben für Sie, damit Sie es nicht müssen.
quelle
Sprachen (wie C ++ 11 ) sind Spezifikationen auf Papier, die normalerweise in Englisch geschrieben sind. Schauen Sie sich den neuesten C ++ 11-Entwurf an (oder kaufen Sie die teure endgültige Spezifikation bei Ihrem ISO-Anbieter).
Sie verwenden im Allgemeinen einen Computer mit einer Sprachimplementierung (Sie könnten ein C ++ - Programm im Prinzip ohne Computer ausführen, z. B. mit einer Gruppe menschlicher Sklaven, die es interpretieren; das wäre unethisch und ineffizient).
Ihre allgemeine C ++ - Implementierung funktioniert über einem bestimmten Betriebssystem und kommuniziert mit diesem (unter Verwendung eines implementierungsspezifischen Codes, häufig in einer Systembibliothek). Im Allgemeinen erfolgt diese Kommunikation über Systemaufrufe . Suchen Sie beispielsweise in syscalls (2) nach einer Liste der auf dem Linux-Kernel verfügbaren Systemaufrufe .
Aus Sicht der Anwendung ist ein Syscall eine elementare Maschinenanweisung wie
SYSENTER
auf x86-64 mit einigen Konventionen ( ABI ).Auf meinem Linux-Desktop befinden sich die Qt-Bibliotheken über den X11- Client-Bibliotheken, die über X Windows-Protokolle mit dem X11-Server Xorg kommunizieren .
Verwenden Sie unter Linux
ldd
Ihre ausführbare Datei, um die (lange) Liste der Abhängigkeiten von Bibliotheken anzuzeigen. Verwendenpmap
Sie diese Option, um zu sehen, welche zur Laufzeit "geladen" werden. Übrigens, unter Linux verwendet Ihre Anwendung wahrscheinlich nur freie Software. Sie können den Quellcode (von Qt über Xlib, libc, ... den Kernel) studieren, um mehr darüber zu erfahren, was passiertquelle
Ich denke, das Konzept, das Sie vermissen, sind Systemaufrufe . Jedes Betriebssystem bietet eine enorme Menge an Ressourcen und Funktionen, auf die Sie zugreifen können, um Betriebssysteme auf niedriger Ebene auszuführen. Selbst wenn Sie eine reguläre Bibliotheksfunktion aufrufen, wird wahrscheinlich hinter den Kulissen ein Systemaufruf ausgeführt.
Systemaufrufe sind eine einfache Möglichkeit, die Leistung des Betriebssystems zu nutzen. Sie können jedoch komplex und umständlich zu verwenden sein. Sie werden daher häufig in APIs "eingeschlossen", damit Sie sich nicht direkt mit ihnen befassen müssen. Aber fast alles, was Sie tun, was O / S-bezogene Ressourcen betrifft, verwendet Systemaufrufe, einschließlich Drucken, Netzwerk und Sockets usw.
Bei Windows ist die GUI von Microsoft Windows tatsächlich in den Kernel geschrieben. Daher gibt es Systemaufrufe zum Erstellen von Fenstern, Zeichnen von Grafiken usw. In anderen Betriebssystemen ist die GUI möglicherweise nicht Teil des Kernels. In diesem Fall Soweit ich weiß, würde es keine Systemaufrufe für GUI-bezogene Dinge geben, und Sie könnten nur auf einer noch niedrigeren Ebene mit den verfügbaren Grafiken und eingabebezogenen Aufrufen auf niedriger Ebene arbeiten.
quelle
Gute Frage. Jeder neue C- oder C ++ - Entwickler hat dies im Sinn. Ich gehe für den Rest dieses Beitrags von einer Standard-x86-Maschine aus. Wenn Sie den Microsoft C ++ - Compiler verwenden, öffnen Sie Ihren Editor und geben Sie diesen ein (nennen Sie die Datei Test.c).
Und jetzt kompilieren Sie diese Datei (mit der Entwickler-Eingabeaufforderung) cl Test.c /FaTest.asm
Öffnen Sie nun Test.asm in Ihrem Notizblock. Was Sie sehen, ist der übersetzte Code - C / C ++ wird in Assembler übersetzt. Verstehst du den Hinweis?
C / C ++ - Programme können auf dem Metall ausgeführt werden. Dies bedeutet, dass sie Zugriff auf Hardware niedrigerer Ebene haben, wodurch es einfacher wird, die Funktionen der Hardware zu nutzen. Angenommen, ich werde eine C-Bibliothek getch () auf einem x86-Computer schreiben.
Abhängig vom Assembler würde ich etwas folgendermaßen eingeben:
Ich führe es mit einem Assembler aus und generiere eine .OBJ - Nenne es getch.obj.
Ich schreibe dann ein C-Programm (ich schließe nichts ein)
Nennen Sie diese Datei nun GetChTest.c. Kompilieren Sie diese Datei, indem Sie getch.obj weitergeben. (Oder kompilieren Sie einzeln zu .obj und LINK GetChTest.Obj und getch.Obj zusammen, um GetChTest.exe zu erstellen.)
Führen Sie GetChTest.exe aus und Sie werden feststellen, dass es auf die Tastatureingabe wartet.
Bei der C / C ++ - Programmierung geht es nicht nur um Sprache. Um ein guter C / C ++ - Programmierer zu sein, müssen Sie ein gutes Verständnis für den Typ des Computers haben, auf dem er ausgeführt wird. Sie müssen wissen, wie die Speicherverwaltung gehandhabt wird, wie die Register aufgebaut sind usw. Sie benötigen möglicherweise nicht alle diese Informationen für die reguläre Programmierung - aber sie würden Ihnen immens helfen. Abgesehen von den grundlegenden Hardware-Kenntnissen ist es sicherlich hilfreich, wenn Sie verstehen, wie der Compiler funktioniert (dh wie er übersetzt wird) - was es Ihnen ermöglichen könnte, Ihren Code nach Bedarf zu optimieren. Es ist ein interessantes Paket!
Beide Sprachen unterstützen das Schlüsselwort __asm, dh Sie können auch Ihren Assembler-Code mischen. Wenn Sie C und C ++ lernen, werden Sie insgesamt zu einem runderen Programmierer.
Es ist nicht notwendig, immer eine Verbindung mit Assembler herzustellen. Ich hatte es erwähnt, weil ich dachte, das würde dir helfen, besser zu verstehen. Meistens verwenden die meisten dieser Bibliotheksaufrufe Systemaufrufe / APIs, die vom Betriebssystem bereitgestellt werden (das Betriebssystem übernimmt wiederum die Hardware-Interaktion).
quelle
Die Verwendung anderer Bibliotheken ist nicht magisch. Bibliotheken sind einfache große Taschen mit Funktionen, die Sie aufrufen können.
Stellen Sie sich vor, Sie schreiben eine solche Funktion
Wenn Sie diese Datei jetzt einschließen, können Sie schreiben
addExclamation(myVeryOwnString);
. Nun könnten Sie sich fragen: "Wie hat C ++ plötzlich die Möglichkeit erhalten, einer Zeichenfolge Ausrufezeichen hinzuzufügen?" Die Antwort ist einfach: Sie haben eine Funktion dafür geschrieben und sie dann aufgerufen.Um Ihre Frage zu beantworten, wie C ++ Funktionen zum Zeichnen von Fenstern durch in C ++ geschriebene Bibliotheken erhalten kann, ist die Antwort dieselbe. Jemand anderes hat dazu Funktionen geschrieben, diese dann kompiliert und Ihnen in Form einer Bibliothek übergeben.
Die anderen Fragen beantworten, wie die Fensterzeichnung tatsächlich funktioniert, aber Sie klangen verwirrt darüber, wie Bibliotheken funktionieren, und ich wollte den grundlegendsten Teil Ihrer Frage ansprechen.
quelle
Der Schlüssel ist die Möglichkeit des Betriebssystems, eine API verfügbar zu machen, und eine detaillierte Beschreibung, wie diese API verwendet werden soll.
Das Betriebssystem bietet eine Reihe von APIs mit Aufrufkonventionen. Die Aufrufkonvention definiert, wie ein Parameter in die API eingegeben wird, wie Ergebnisse zurückgegeben werden und wie der eigentliche Aufruf ausgeführt wird.
Betriebssysteme und die Compiler, die Code für sie erstellen, spielen gut zusammen, sodass Sie normalerweise nicht darüber nachdenken müssen, sondern sie nur verwenden müssen.
quelle
Zum Erstellen von Fenstern ist keine spezielle Syntax erforderlich. Erforderlich ist lediglich, dass das Betriebssystem eine API zum Erstellen von Fenstern bereitstellt. Eine solche API besteht aus einfachen Funktionsaufrufen, für die C ++ Syntax bereitstellt.
Darüber hinaus sind C und C ++ sogenannte Systemprogrammiersprachen und können auf beliebige Zeiger zugreifen (die möglicherweise von der Hardware einem bestimmten Gerät zugeordnet werden). Darüber hinaus ist es auch recht einfach, in Assembly definierte Funktionen aufzurufen, die den gesamten Funktionsumfang des Prozessors ermöglichen. Daher ist es möglich, ein Betriebssystem selbst mit C oder C ++ und einer kleinen Menge an Assembly zu schreiben.
Es sollte auch erwähnt werden, dass Qt ein schlechtes Beispiel ist, da es einen sogenannten Meta-Compiler verwendet um die C ++ - Syntax zu erweitern. Dies hängt jedoch nicht mit der Fähigkeit zusammen, die vom Betriebssystem bereitgestellten APIs aufzurufen, um tatsächlich Fenster zu zeichnen oder zu erstellen.
quelle
Erstens gibt es ein kleines Missverständnis, denke ich
Es gibt keine Syntax für Betriebssystemoperationen. Es ist die Frage der Semantik .
Nun, das Betriebssystem ist meistens in C geschrieben. Sie können gemeinsam genutzte Bibliotheken (also DLL) verwenden, um den externen Code aufzurufen. Darüber hinaus kann der Betriebssystemcode Systemroutinen auf Systemaufrufen * oder Interrupts registrieren, die Sie mithilfe von Assembly aufrufen können . Da gemeinsam genutzte Bibliotheken häufig nur Systemaufrufe für Sie ausführen, werden Sie von der Inline-Assembly verschont.
Hier ist das nette Tutorial dazu: http://www.win.tue.nl/~aeb/linux/lk/lk-4.html
Es ist für Linux, aber die Prinzipien sind dieselben.
Wie arbeitet das Betriebssystem mit Grafikkarten, Netzwerkkarten usw.? Es ist ein sehr breites Thema, aber meistens müssen Sie auf Interrupts, Ports zugreifen oder Daten in einen speziellen Speicherbereich schreiben. Da diese Vorgänge geschützt sind, müssen Sie sie trotzdem über das Betriebssystem aufrufen.
quelle
In dem Versuch, andere Antworten etwas anders zu betrachten, werde ich so antworten.
(Haftungsausschluss: Ich vereinfache die Dinge leicht, die Situation, die ich gebe, ist rein hypothetisch und dient dazu, Konzepte zu demonstrieren, anstatt zu 100% dem Leben treu zu bleiben.)
Stellen Sie sich die Dinge aus einer anderen Perspektive vor. Stellen Sie sich vor, Sie haben gerade ein einfaches Betriebssystem mit grundlegenden Funktionen für Threading, Fensterung und Speicherverwaltung geschrieben. Sie möchten eine C ++ - Bibliothek implementieren, mit der Benutzer in C ++ programmieren und beispielsweise Fenster erstellen, auf Fenster zeichnen usw. Die Frage ist, wie dies zu tun ist.
Da C ++ zu Maschinencode kompiliert wird, müssen Sie zunächst eine Möglichkeit definieren, Maschinencode für die Schnittstelle mit C ++ zu verwenden. Hier kommen Funktionen ins Spiel, Funktionen akzeptieren Argumente und geben Rückgabewerte an. Sie bieten somit eine Standardmethode für die Übertragung von Daten zwischen verschiedenen Codeabschnitten. Sie tun dies, indem sie eine sogenannte Rufkonvention etablieren .
Eine aufrufende Konvention gibt an, wo und wie Argumente im Speicher abgelegt werden sollen, damit eine Funktion sie finden kann, wenn sie ausgeführt wird. Wenn eine Funktion aufgerufen wird, legt die aufrufende Funktion die Argumente im Speicher ab und fordert die CPU auf, zur anderen Funktion zu springen, wo sie das tut, was sie tut, bevor sie dorthin zurückspringt, von wo sie aufgerufen wurde. Dies bedeutet, dass der aufgerufene Code absolut alles sein kann und sich nicht ändert, wie die Funktion aufgerufen wird. In diesem Fall wäre der Code hinter der Funktion jedoch für das Betriebssystem relevant und würde mit dem internen Status des Betriebssystems arbeiten.
Viele Monate später haben Sie alle Funktionen Ihres Betriebssystems erledigt. Ihr Benutzer kann Funktionen aufrufen, um Fenster zu erstellen und darauf zu zeichnen. Er kann Threads und alle möglichen wunderbaren Dinge erstellen. Hier ist das Problem: Die Funktionen Ihres Betriebssystems unterscheiden sich von den Funktionen von Linux oder Windows. Sie müssen dem Benutzer also eine Standardschnittstelle geben, damit er tragbaren Code schreiben kann. Hier kommt QT ins Spiel.
Wie Sie mit ziemlicher Sicherheit wissen, verfügt QT über eine Vielzahl nützlicher Klassen und Funktionen, mit denen Sie die Aufgaben von Betriebssystemen ausführen können, die jedoch unabhängig vom zugrunde liegenden Betriebssystem erscheinen. Dies funktioniert so, dass QT Klassen und Funktionen bereitstellt, die in ihrer Darstellung für den Benutzer einheitlich sind, der Code hinter den Funktionen jedoch für jedes Betriebssystem unterschiedlich ist. Zum Beispiel würde QTs QApplication :: closeAllWindows () tatsächlich die spezielle Fensterschließfunktion jedes Betriebssystems aufrufen, abhängig von der verwendeten Version. In Windows würde es höchstwahrscheinlich CloseWindow (hwnd) aufrufen, während es auf einem Betriebssystem, das das X Window System verwendet, möglicherweise XDestroyWindow (Anzeige, Fenster) aufrufen würde.
Es ist offensichtlich, dass ein Betriebssystem viele Schichten hat, die alle über Schnittstellen vieler Arten interagieren müssen. Es gibt viele Aspekte, die ich noch nicht einmal angesprochen habe, aber es würde sehr lange dauern, sie alle zu erklären. Wenn Sie sich weiter für das Innenleben von Betriebssystemen interessieren, empfehle ich Ihnen, das OS-Entwickler-Wiki zu lesen .
Bedenken Sie jedoch, dass viele Betriebssysteme Schnittstellen für C / C ++ verfügbar machen, weil sie zu Maschinencode kompiliert werden, Assembleranweisungen mit ihrem eigenen Code gemischt werden können und dem Programmierer ein hohes Maß an Freiheit bieten.
Auch hier ist viel los. Ich möchte weiter erklären, wie Bibliotheken wie .so und .dll-Dateien nicht in C / C ++ geschrieben werden müssen und in Assembler oder anderen Sprachen geschrieben werden können, aber ich habe das Gefühl, dass ich es auch tun könnte, wenn ich weitere hinzufüge schreibe einen ganzen Artikel, und so gerne ich das tun würde, ich habe keine Seite, auf der ich ihn hosten könnte.
quelle
Wenn Sie versuchen, etwas auf dem Bildschirm zu zeichnen, ruft Ihr Code einen anderen Code auf, der einen anderen Code (usw.) aufruft, bis schließlich ein "Systemaufruf" erfolgt, eine spezielle Anweisung, die die CPU ausführen kann. Diese Anweisungen können entweder in Assembly oder in C ++ geschrieben werden, wenn der Compiler ihre "Intrinsics" unterstützt (Funktionen, die der Compiler "speziell" verarbeitet, indem er sie in speziellen Code konvertiert, den die CPU verstehen kann). Ihre Aufgabe ist es, das Betriebssystem anzuweisen, etwas zu tun.
Wenn ein Systemaufruf erfolgt, wird eine Funktion aufgerufen, die eine andere Funktion (usw.) aufruft, bis der Anzeigetreiber schließlich aufgefordert wird, etwas auf dem Bildschirm zu zeichnen. Zu diesem Zeitpunkt betrachtet der Anzeigetreiber einen bestimmten Bereich im physischen Speicher, der eigentlich kein Speicher ist, sondern einen Adressbereich, in den geschrieben werden kann, als wäre er Speicher. Statt jedoch zu diesem Adressbereich Schreiben bewirkt , dass die Grafik - Hardware zum Abfangen des Speicher - Schreib und etwas auf dem Bildschirm zeichnen.
Das Schreiben in diese Region des Gedächtnisses ist etwas, das es könnte. in C codiert werden ++, da auf der Software - Seite ist es nur ein ganz normaler Speicherzugriff. Es ist nur so, dass die Hardware anders damit umgeht.
Das ist also eine wirklich grundlegende Erklärung, wie es funktionieren kann.
quelle
syscall
(und sein Cousinsysenter
) in der Tat eine CPU-Anweisung ist.sysenter
sind optimierte Aufrufpfade, da die von Interrupt-Handlern verwendete Kontextumschaltung nicht so schnell war, wie alle es wünschten, aber im Grunde ist es immer noch ein durch Software generierter Interrupt, während er durch Vektorisierung an einen vom OS-Kernel installierten Handler behandelt wird. Ein Teil des Kontextumschaltprozesses, den IS durchführt,sysenter
besteht darin, die Modusbits im Prozessor so zu ändern, dass Ring 0 gesetzt wird - vollständiger Zugriff auf alle privilegierten Befehle, Register sowie Speicher- und E / A-Bereiche.Ihr C ++ - Programm verwendet die Qt-Bibliothek (ebenfalls in C ++ codiert). Die Qt-Bibliothek verwendet die Windows- Funktion CreateWindowEx (die in C in kernel32.dll codiert wurde). Oder unter Linux wird möglicherweise Xlib verwendet (ebenfalls in C codiert), aber es können auch die Rohbytes gesendet werden, die im X-Protokoll " Bitte erstellen Sie ein Fenster für mich " bedeuten " .
Bezogen auf Ihren Catch-22 Frage steht der historische Hinweis, dass „der erste C ++ - Compiler in C ++ geschrieben wurde“, obwohl es sich tatsächlich um einen C-Compiler mit einigen C ++ - Begriffen handelte, der ausreichte, um die erste Version zu kompilieren, die sich dann selbst kompilieren konnte .
In ähnlicher Weise verwendet der GCC-Compiler GCC-Erweiterungen: Er wird zuerst zu einer Version kompiliert und dann zum erneuten Kompilieren verwendet. (GCC Build-Anweisungen)
quelle
Wie ich die Frage sehe, ist dies eigentlich eine Compiler-Frage.
Betrachten Sie es so, Sie schreiben einen Code in Assembly (Sie können ihn in jeder Sprache ausführen), der Ihre neu geschriebene Sprache, die Sie Z ++ aufrufen möchten, in Assembly übersetzt. Der Einfachheit halber können Sie sie als Compiler bezeichnen (es ist ein Compiler). .
Jetzt geben Sie diesem Compiler einige grundlegende Funktionen, damit Sie int, string, arrays usw. schreiben können. Tatsächlich geben Sie ihm genügend Fähigkeiten, damit Sie den Compiler selbst in Z ++ schreiben können. und jetzt haben Sie einen Compiler für Z ++ in Z ++ geschrieben, ziemlich ordentlich richtig.
Was noch cooler ist, ist, dass Sie diesem Compiler jetzt Fähigkeiten hinzufügen können, indem Sie die bereits vorhandenen Fähigkeiten verwenden, wodurch die Z ++ - Sprache durch die Verwendung der vorherigen Funktionen um neue Funktionen erweitert wird
Wenn Sie beispielsweise genügend Code schreiben, um ein Pixel in einer beliebigen Farbe zu zeichnen, können Sie es mit Z ++ erweitern, um alles zu zeichnen, was Sie möchten.
quelle
Die Hardware ermöglicht dies. Sie können sich den Grafikspeicher als großes Array vorstellen (bestehend aus jedem Pixel auf dem Bildschirm). Um auf den Bildschirm zu zeichnen, können Sie mit C ++ oder einer beliebigen Sprache, die den direkten Zugriff auf diesen Speicher ermöglicht, in diesen Speicher schreiben. Dieser Speicher ist zufällig für die Grafikkarte zugänglich oder befindet sich auf dieser.
Auf modernen Systemen, die direkt auf den Grafikspeicher zugreifen, muss aufgrund verschiedener Einschränkungen ein Treiber geschrieben werden, sodass Sie indirekte Mittel verwenden. Bibliotheken, die ein Fenster erstellen (eigentlich nur ein Bild wie jedes andere Bild) und dieses Bild dann in den Grafikspeicher schreiben, den die GPU dann auf dem Bildschirm anzeigt. Der Sprache muss nichts hinzugefügt werden, außer der Fähigkeit, in bestimmte Speicherorte zu schreiben, wofür Zeiger gedacht sind.
quelle