我正在学习c++,我刚刚开始学习Qt的一些功能来编写GUI程序。我问了自己以下问题:

c++以前没有语法能够要求操作系统提供一个窗口或一种通过网络进行通信的方式(我承认我也不完全理解api),它是如何通过c++本身编写的库突然获得这些功能的?在我看来,这一切都是可怕的循环。你能在这些库中找到哪些c++指令?

我知道这个问题对一个有经验的软件开发人员来说似乎微不足道,但我已经研究了几个小时,没有找到任何直接的回答。这已经到了我无法理解Qt教程的地步,因为库的存在对我来说是不可理解的。


当前回答

您的c++程序使用Qt库(也是用c++编写的)。Qt库将使用Windows CreateWindowEx函数(在kernel32.dll中用C编写)。或者在Linux下,它可能使用Xlib(也是用C编写的),但它也可以发送原始字节,在X协议中意味着“请为我创建一个窗口”。

与你的两难问题相关的是“第一个c++编译器是用c++编写的”的历史注释,尽管实际上它是一个带有一些c++概念的C编译器,足以编译第一个版本,然后它可以编译自己。

类似地,GCC编译器使用GCC扩展:它首先被编译到一个版本,然后用于重新编译自身。(GCC构建说明)

其他回答

关键在于操作系统是否可能公开API以及如何使用该API的详细描述。

操作系统提供了一组具有调用约定的api。 调用约定定义了将参数提供给API的方式、返回结果的方式以及如何执行实际调用。

操作系统和为它们创建代码的编译器可以很好地协同工作,所以您通常不必考虑它,只需使用它。

C和c++有两个属性,允许OP所谈论的所有这些可扩展性。

C和c++可以访问内存 C和c++可以调用非C或c++语言中的汇编代码。

在内核或基本的非保护模式平台中,外围设备(如串口或磁盘驱动器)以与RAM相同的方式映射到内存映射中。内存是一系列的开关,翻转外围设备的开关(比如串口或磁盘驱动器)可以让外围设备做一些有用的事情。

在保护模式操作系统中,当用户希望从用户空间访问内核时(比如写入文件系统或在屏幕上绘制像素),需要进行系统调用。C语言没有指令来进行系统调用,但是C语言可以调用汇编代码来触发正确的系统调用,这就是为什么C代码可以与内核对话。

为了使特定平台的编程更容易,系统调用被包装在更复杂的函数中,这些函数可以在自己的程序中执行一些有用的函数。可以直接调用系统调用(使用汇编程序),但是使用平台提供的一个包装器函数可能更容易。

还有另一层API比系统调用有用得多。以malloc为例。这不仅会调用系统来获取大块的内存,而且还会通过对正在发生的事情进行所有簿记来管理这些内存。

Win32 api用一个公共平台小部件集包装了一些图形功能。Qt更进一步,以跨平台的方式包装了Win32(或X Windows) API。

从根本上讲,C编译器将C代码转换为机器代码,由于计算机被设计为使用机器代码,所以你应该期望C能够完成计算机所能完成的大部分工作。包装器库所做的一切都是为您做繁重的工作,这样您就不必做了。

我认为你忽略了系统调用的概念。每个操作系统都提供了大量的资源和功能,您可以利用它们来做与操作系统相关的底层工作。即使当您调用常规的库函数时,它也可能在幕后进行系统调用。

系统调用是一种利用操作系统强大功能的低级方式,但使用起来可能复杂且麻烦,因此通常被“包装”在api中,这样您就不必直接处理它们。但实际上,几乎所有涉及O/S相关资源的操作都将使用系统调用,包括打印、网络和套接字等。

在windows的情况下,微软windows已经把它的GUI写进了内核,所以有一些系统调用来创建窗口,绘制图形等。在其他操作系统中,GUI可能不是内核的一部分,在这种情况下,据我所知,不会有任何与GUI相关的系统调用,您只能在更低的级别上使用任何可用的低级图形和输入相关调用。

为了提供与其他答案略有不同的观点,我将这样回答。

(免责声明:我只是稍微简化了事情,我给出的情况纯粹是假设的,是作为演示概念的一种手段而写的,而不是100%真实的生活)。

从另一个角度考虑问题,假设您刚刚编写了一个简单的操作系统,具有基本的线程、窗口和内存管理功能。你想要实现一个c++库,让用户用c++编程,做一些事情,比如创建窗口,在窗口上绘图等等。问题是,如何做到这一点。

首先,由于c++编译为机器代码,您需要定义一种使用机器代码与c++进行接口的方法。这就是函数的作用所在,函数接受参数并给出返回值,因此它们提供了在不同代码段之间传输数据的标准方式。他们通过建立一种称为调用约定的东西来做到这一点。

A calling convention states where and how arguments should be placed in memory so that a function can find them when it gets executed. When a function gets called, the calling function places the arguments in memory and then asks the CPU to jump over to the other function, where it does what it does before jumping back to where it was called from. This means that the code being called can be absolutely anything and it will not change how the function is called. In this case however, the code behind the function would be relevant to the operating system and would operate on the operating system's internal state.

所以,几个月后,你已经整理好了所有的操作系统功能。你的用户可以调用函数来创建窗口并在上面绘图,他们可以创建线程和所有美妙的东西。但问题是,你的操作系统的功能将不同于Linux或Windows的功能。所以你决定给用户一个标准的界面,这样他们就可以编写可移植的代码。这就是QT的用武之地。

As you almost certainly know, QT has loads of useful classes and functions for doing the sorts of things that operating systems do, but in a way that appears independent of the underlying operating system. The way this works is that QT provides classes and functions that are uniform in the way they appear to the user, but the code behind the functions is different for each operating system. For example QT's QApplication::closeAllWindows() would actually be calling each operating system's specialised window closing function depending on the version used. In Windows it would most likely call CloseWindow(hwnd) whereas on an os using the X Window System, it would potentially call XDestroyWindow(display,window).

很明显,操作系统有很多层,所有这些层都必须通过各种各样的接口进行交互。有许多方面我还没有谈到,但要全部解释它们将需要很长时间。如果您对操作系统的内部工作原理有进一步的兴趣,我建议您查看OS dev wiki。

请记住,许多操作系统选择向C/ c++公开接口的原因是它们可以编译为机器代码,它们允许将汇编指令与它们自己的代码混合在一起,并且它们为程序员提供了很大程度的自由。

同样,这里有很多内容。我想继续解释库如何像.so和.dll文件不需要用C/ c++编写,可以用汇编或其他语言编写,但我觉得如果我再添加更多,我还不如写一整篇文章,尽管我很想这样做,但我没有一个站点来托管它。

首先,我觉得有一点误会

c++以前没有语法能够要求操作系统提供一个窗口或一种通过网络通信的方式,它是如何做到的呢

没有用于操作系统操作的语法。这是语义学的问题。

突然通过c++本身编写的库获得这些功能

操作系统主要是用c编写的。您可以使用共享库(即dll)来调用外部代码。此外,操作系统代码可以在系统调用*或中断上注册系统例程,您可以使用程序集调用这些例程。共享库通常只是为您进行系统调用,因此您可以避免使用内联汇编。

这里有一个很好的教程:http://www.win.tue.nl/~aeb/linux/lk/lk-4.html 它适用于Linux,但原理是相同的。

操作系统如何对显卡、网卡等进行操作?这是一个非常广泛的主题,但大多数情况下你需要访问中断,端口或写入一些数据到特殊的内存区域。由于这些操作是受保护的,所以无论如何都需要通过操作系统调用它们。