En un intento de proporcionar una visión ligeramente diferente a otras respuestas, responderé así.
(Descargo de responsabilidad: estoy simplificando un poco las cosas, la situación que doy es puramente hipotética y está escrita como un medio para demostrar conceptos en lugar de ser 100% fiel a la vida).
Piense en las cosas desde la otra perspectiva, imagine que acaba de escribir un sistema operativo simple con capacidades básicas de enhebrado, ventanas y administración de memoria. Desea implementar una biblioteca C ++ para permitir que los usuarios programen en C ++ y hagan cosas como hacer ventanas, dibujar en ventanas, etc. La pregunta es cómo hacer esto.
En primer lugar, dado que C ++ compila el código de la máquina, debe definir una forma de utilizar el código de la máquina para interactuar con C ++. Aquí es donde entran las funciones, las funciones aceptan argumentos y dan valores de retorno, por lo que proporcionan una forma estándar de transferir datos entre diferentes secciones de código. Lo hacen estableciendo algo conocido como una convención de convocatoria .
Una convención de llamada establece dónde y cómo deben colocarse los argumentos en la memoria para que una función pueda encontrarlos cuando se ejecuta. Cuando se llama a una función, la función de llamada coloca los argumentos en la memoria y luego le pide a la CPU que salte a la otra función, donde hace lo que hace antes de volver a donde fue llamada. Esto significa que el código que se llama puede ser absolutamente cualquier cosa y no cambiará cómo se llama la función. Sin embargo, en este caso, el código detrás de la función sería relevante para el sistema operativo y funcionaría en el estado interno del sistema operativo.
Entonces, muchos meses después y tienes todas tus funciones del sistema operativo ordenadas. Su usuario puede llamar a funciones para crear ventanas y dibujar en ellas, puede hacer hilos y todo tipo de cosas maravillosas. Sin embargo, aquí está el problema, las funciones de su sistema operativo serán diferentes a las funciones de Linux o de Windows. Por lo tanto, decide que necesita darle al usuario una interfaz estándar para que pueda escribir código portátil. Aquí es donde entra QT.
Como es casi seguro que sabe, QT tiene muchas clases y funciones útiles para hacer las cosas que hacen los sistemas operativos, pero de una manera que parece independiente del sistema operativo subyacente. La forma en que esto funciona es que QT proporciona clases y funciones que son uniformes en la forma en que aparecen para el usuario, pero el código detrás de las funciones es diferente para cada sistema operativo. Por ejemplo, QApplication :: closeAllWindows () de QT realmente llamaría a la función de cierre de ventana especializada de cada sistema operativo, dependiendo de la versión utilizada. En Windows, lo más probable es que llame a CloseWindow (hwnd), mientras que en un sistema operativo que usa el sistema X Window, podría llamar a XDestroyWindow (pantalla, ventana).
Como es evidente, un sistema operativo tiene muchas capas, todas las cuales deben interactuar a través de interfaces de muchas variedades. Hay muchos aspectos que ni siquiera he mencionado, pero explicarlos llevaría mucho tiempo. Si está más interesado en el funcionamiento interno de los sistemas operativos, le recomiendo consultar el wiki de desarrollo del sistema operativo .
Sin embargo, tenga en cuenta que la razón por la que muchos sistemas operativos eligen exponer las interfaces a C / C ++ es que compilan el código de la máquina, permiten que las instrucciones de ensamblaje se mezclen con su propio código y brindan un gran grado de libertad al programador.
Una vez más, están pasando muchas cosas aquí. Me gustaría continuar explicando cómo las bibliotecas como .so y .dll no tienen que escribirse en C / C ++ y pueden escribirse en ensamblador u otros lenguajes, pero siento que si agrego más, también podría escribir un artículo completo, y por mucho que me gustaría hacer eso, no tengo un sitio para alojarlo.