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

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

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


当前回答

硬件是允许这一切发生的原因。您可以将图形存储器看作一个大数组(由屏幕上的每个像素组成)。要绘制到屏幕上,您可以使用c++或任何允许直接访问该内存的语言写入该内存。该内存恰好可以被显卡访问或位于显卡上。

在现代系统中,由于各种限制,直接访问图形存储器需要编写驱动程序,因此您可以使用间接方法。库创建一个窗口(实际上只是一个像其他图像一样的图像),然后将该图像写入图形内存,然后GPU将其显示在屏幕上。除了写入特定内存位置的能力之外,该语言不需要添加任何东西,这就是指针的作用。

其他回答

计算机就像一个洋葱,它有很多很多层,从纯硬件的内核到最外层的应用层。每一层都将自己的一部分暴露给下一个外层,这样外层就可以使用内层的一些功能。

以Windows为例,操作系统为运行在Windows上的应用程序公开了所谓的WIN32 API。Qt库使用该API为使用Qt的应用程序提供自己的API。你使用Qt, Qt使用WIN32, WIN32使用较低级别的Windows操作系统,等等,直到它成为硬件中的电信号。

c++是如何…突然通过库获得这些功能 用c++写的?

使用其他库并没有什么神奇的。库是可以调用的简单的大函数包。

假设你在写一个这样的函数

void addExclamation(std::string &str)
{
    str.push_back('!');
}

现在如果你包含这个文件,你可以写addex叹号(myVeryOwnString);。现在你可能会问,“c++是怎么突然有能力在字符串中添加感叹号的?”答案很简单:你写一个函数来做这件事,然后你调用它。

因此,要回答你关于c++如何通过c++编写的库获得绘制窗口的能力的问题,答案是相同的。其他人写函数来做这些,然后编译它们,并以库的形式提供给你。

其他问题回答了窗口绘图的实际工作方式,但你听起来对库的工作方式感到困惑,所以我想解决你问题中最基本的部分。

When you try to draw something on the screen, your code calls some other piece of code which calls some other code (etc.) until finally there is a "system call", which is a special instruction that the CPU can execute. These instructions can be either written in assembly or can be written in C++ if the compiler supports their "intrinsics" (which are functions that the compiler handles "specially" by converting them into special code that the CPU can understand). Their job is to tell the operating system to do something.

When a system call happens, a function gets called that calls another function (etc.) until finally the display driver is told to draw something on the screen. At that point, the display driver looks at a particular region in physical memory which is actually not memory, but rather an address range that can be written to as if it were memory. Instead, however, writing to that address range causes the graphics hardware to intercept the memory write, and draw something on the screen. Writing to this region of memory is something that could be coded in C++, since on the software side it's just a regular memory access. It's just that the hardware handles it differently. So that's a really basic explanation of how it can work.

语言(如c++ 11)是纸上的规范,通常用英语编写。看看最新的c++ 11草案(或者从ISO供应商那里购买昂贵的最终规范)。

你通常使用带有语言实现的计算机(原则上你可以在没有任何计算机的情况下运行c++程序,例如使用一群人类奴隶来解释它;那样既不道德又低效)

你的c++实现通常工作在某个操作系统之上,并与它通信(使用一些特定于实现的代码,通常在一些系统库中)。通常这种通信是通过系统调用完成的。在instance into syscalls(2)中查找Linux内核上可用的系统调用列表。

从应用程序的角度来看,系统调用是一个基本的机器指令,就像x86-64上的SYSENTER一样,具有一些约定(ABI)。

在我的Linux桌面上,Qt库位于X11客户端库之上,通过X Windows协议与X11服务器Xorg通信。

在Linux上,在可执行文件上使用ldd来查看对库的依赖项的(长)列表。在正在运行的进程上使用pmap查看在运行时“加载”了哪些文件。顺便说一句,在Linux上,你的应用程序可能只使用免费软件,你可以研究它的源代码(从Qt,到Xlib, libc,…内核)以了解更多正在发生的事情

创建窗口不需要特殊的语法。所需要的只是操作系统提供一个API来创建窗口。这样的API由c++提供语法的简单函数调用组成。

此外,C和c++是所谓的系统编程语言,能够访问任意指针(可能由硬件映射到某些设备)。此外,调用在程序集中定义的函数也相当简单,这允许处理器提供的全部操作。因此,使用C或c++和少量的汇编程序来编写操作系统本身是可能的。

还应该提到Qt是一个不好的例子,因为它使用所谓的元编译器来扩展c++的语法。然而,这与它调用操作系统提供的api来实际绘制或创建窗口的能力无关。