Nel tentativo di fornire una visione leggermente diversa alle altre risposte, risponderò in questo modo.
(Dichiarazione di non responsabilità: sto semplificando leggermente le cose, la situazione che do è puramente ipotetica ed è scritta come mezzo per dimostrare concetti piuttosto che essere fedele al 100% alla vita).
Pensa alle cose dall'altra prospettiva, immagina di aver appena scritto un semplice sistema operativo con funzionalità di threading, windowing e gestione della memoria di base. Volete implementare una libreria C ++ per consentire agli utenti di programmare in C ++ e fare cose come creare finestre, disegnare su Windows ecc. La domanda è: come farlo.
Innanzitutto, poiché il C ++ viene compilato in base al codice macchina, è necessario definire un modo per utilizzare il codice macchina per interfacciarsi con il C ++. È qui che entrano in gioco le funzioni, le funzioni accettano argomenti e danno valori di ritorno, quindi forniscono un modo standard per trasferire dati tra diverse sezioni di codice. Lo fanno stabilendo qualcosa noto come convenzione di chiamata .
Una convenzione di chiamata indica dove e come gli argomenti devono essere collocati in memoria in modo che una funzione possa trovarli quando viene eseguita. Quando viene chiamata una funzione, la funzione chiamante inserisce gli argomenti in memoria e quindi chiede alla CPU di passare all'altra funzione, dove fa quello che fa prima di tornare da dove è stata chiamata. Ciò significa che il codice chiamato può essere assolutamente qualsiasi cosa e non cambierà il modo in cui viene chiamata la funzione. In questo caso, tuttavia, il codice dietro la funzione sarebbe rilevante per il sistema operativo e opererebbe sullo stato interno del sistema operativo.
Quindi, molti mesi dopo e hai sistemato tutte le funzioni del tuo sistema operativo. Il tuo utente può chiamare funzioni per creare finestre e disegnare su di esse, può creare discussioni e ogni sorta di cose meravigliose. Questo è il problema, tuttavia, le funzioni del tuo sistema operativo saranno diverse dalle funzioni di Linux o di Windows. Quindi decidi che devi fornire all'utente un'interfaccia standard in modo che possano scrivere codice portatile. Qui è dove entra in gioco QT.
Come quasi sicuramente saprai, QT ha molte classi e funzioni utili per fare il genere di cose che fanno i sistemi operativi, ma in un modo che sembra indipendente dal sistema operativo sottostante. Il modo in cui funziona è che QT fornisce classi e funzioni uniformi nel modo in cui appaiono all'utente, ma il codice dietro le funzioni è diverso per ogni sistema operativo. Ad esempio, QApplication :: closeAllWindows () di QT chiamerebbe effettivamente la funzione di chiusura della finestra specializzata di ciascun sistema operativo a seconda della versione utilizzata. In Windows molto probabilmente chiamerebbe CloseWindow (hwnd) mentre su un sistema operativo che utilizza X Window System, potenzialmente chiamerebbe XDestroyWindow (display, finestra).
Come è evidente, un sistema operativo ha molti livelli, che devono interagire attraverso interfacce di molte varietà. Ci sono molti aspetti che non ho nemmeno toccato, ma spiegarli tutti richiederebbe molto tempo. Se sei ulteriormente interessato al funzionamento interno dei sistemi operativi, ti consiglio di dare un'occhiata al wiki del dev del sistema operativo .
Tenete presente, tuttavia, che la ragione per cui molti sistemi operativi scelgono di esporre le interfacce in C / C ++ è che si compilano in base al codice macchina, permettono alle istruzioni di assemblaggio di essere mescolate con il proprio codice e offrono un grande grado di libertà al programmatore.
Ancora una volta, c'è molto da fare qui. Vorrei continuare a spiegare come le librerie come i file .so e .dll non debbano essere scritte in C / C ++ e possano essere scritte in assembly o in altre lingue, ma sento che se ne aggiungessi altre potrei anche scrivere un intero articolo e per quanto mi piacerebbe fare non ho un sito su cui ospitarlo.