Próbując przedstawić nieco inne spojrzenie na inne odpowiedzi, odpowiem w ten sposób.
(Oświadczenie: Upraszczam nieco, sytuacja, którą podaję, jest czysto hipotetyczna i została napisana jako środek demonstracji koncepcji, a nie bycia w 100% wiernym życiu).
Pomyśl o tym z innej perspektywy, wyobraź sobie, że właśnie napisałeś prosty system operacyjny z podstawowymi funkcjami wątkowania, okienkowania i zarządzania pamięcią. Chcesz zaimplementować bibliotekę C ++, aby umożliwić użytkownikom programowanie w C ++ i wykonywanie takich czynności, jak tworzenie okien, rysowanie na oknach itp. Pytanie brzmi, jak to zrobić.
Po pierwsze, ponieważ C ++ kompiluje się do kodu maszynowego, musisz zdefiniować sposób użycia kodu maszynowego do interfejsu z C ++. To tutaj przychodzą funkcje, funkcje akceptują argumenty i zwracają wartości, dzięki czemu zapewniają standardowy sposób przesyłania danych między różnymi sekcjami kodu. Robią to, ustanawiając coś, co nazywa się konwencją powołania .
A konwencja wywoływania stanów, gdzie i jak argumenty powinny być umieszczane w pamięci tak, że funkcja może ich znaleźć, gdy zostanie wykonany. Kiedy funkcja zostaje wywołana, funkcja wywołująca umieszcza argumenty w pamięci, a następnie prosi CPU, aby przeskoczył do innej funkcji, gdzie robi to, co robi, zanim wróci do miejsca, z którego został wywołany. Oznacza to, że wywoływany kod może być absolutnie dowolny i nie zmienia sposobu wywoływania funkcji. W takim przypadku kod stojący za funkcją byłby odpowiedni dla systemu operacyjnego i działałby w stanie wewnętrznym systemu operacyjnego.
Wiele miesięcy później masz już uporządkowane wszystkie funkcje systemu operacyjnego. Użytkownik może wywoływać funkcje w celu tworzenia okien i rysowania na nich, może tworzyć wątki i wszelkiego rodzaju wspaniałe rzeczy. Oto problem: funkcje twojego systemu będą się różnić od funkcji Linuksa lub Windowsa. Więc decydujesz, że musisz dać użytkownikowi standardowy interfejs, aby mógł pisać przenośny kod. Tutaj pojawia się QT.
Jak prawie na pewno wiesz, QT ma mnóstwo przydatnych klas i funkcji do robienia tego, co robią systemy operacyjne, ale w sposób, który wydaje się niezależny od bazowego systemu operacyjnego. Działa to w ten sposób, że QT zapewnia klasy i funkcje, które są jednolite pod względem wyglądu dla użytkownika, ale kod stojący za funkcjami jest inny dla każdego systemu operacyjnego. Na przykład QApplication :: closeAllWindows () QT faktycznie wywoływałby specjalną funkcję zamykania okien każdego systemu operacyjnego w zależności od używanej wersji. W Windows najprawdopodobniej wywołałby CloseWindow (hwnd), podczas gdy w systemie operacyjnym korzystającym z X Window System potencjalnie wywołałby XDestroyWindow (display, window).
Jak widać, system operacyjny ma wiele warstw, z których wszystkie muszą oddziaływać poprzez interfejsy wielu odmian. Jest wiele aspektów, których nawet nie dotknąłem, ale ich wyjaśnienie zajęłoby bardzo dużo czasu. Jeśli jesteś zainteresowany wewnętrznymi działaniami systemów operacyjnych, polecam sprawdzenie wiki dla programistów systemu operacyjnego .
Należy jednak pamiętać, że powodem, dla którego wiele systemów operacyjnych decyduje się na udostępnienie interfejsów C / C ++, jest to, że kompilują się one do kodu maszynowego, pozwalają na mieszanie instrukcji asemblera z własnym kodem i zapewniają programistom dużą swobodę.
Znowu wiele się tu dzieje. Chciałbym wyjaśnić, w jaki sposób biblioteki takie jak .so i .dll nie muszą być pisane w C / C ++ i mogą być napisane w asemblerze lub w innych językach, ale wydaje mi się, że jeśli coś jeszcze dodam, równie dobrze napisz cały artykuł i tak bardzo, jak chciałbym to zrobić, nie mam witryny, w której można by go hostować.