独钓寒江雪

用C++的优雅,驯服Windows的狂野

在早期的 Windows 操作系统中,在同一用户下运行的所有进程有着相同的安全等级,拥有相同的权限。此时进程可以自由地发送Windows 消息到其他进程的窗口。

从 Windows Vista 开始,对于某些 Windows 消息,这一方式再也行不通了,进程(或者其他的对象)开始拥有一个新的属性–特权等级(Privilege Level)。此时一个特权等级较低的进程不再可以向特权等级较高的进程发送消息,即便他们在相同的用户权限下运行也不行,这就是所谓的用户界面特权隔离(User Interface Privilege Isolation, 简称 UIPI)。

阅读全文 »

C++代码编译流程

以下面 C++代码为例:

1
2
3
4
5
6
7
#include <stdio.h>

int main()
{
printf("Hello World");
return 0;
}

编译成二进制文件需要经过如下 4 个过程:

  • 预编译:将 hello.c 和 stdio.h 预编译为 hello.i
  • 编译:将 hello.i 编译为 hello.s
  • 汇编:将 hello.s 翻译为机器指令 hello.o(.o 目标文件)
  • 链接:链接各种需要的库和其他目标文件(该 hello 程序不需要)得到可执行文件 hello.out(相当于 windows 的.exe)。
阅读全文 »

《C++ API 设计》是一本非常不错的书,该书内容远远超过了它标题所指的 C++ API 设计,它不仅仅讲述了与编程语言无关的 API 设计需要遵循的一些规范,同时也介绍了很多 C++开发中需要遵守一些准则,如果在开发中能遵循这些准则,将有利于我们写出高质量的代码。

阅读全文 »

什么是内核对象

我们在 windows 开发中经常会遇到内核对象,如事件(Event),管道(Pipe),互斥量(Mutex),完成端口(IOCP),进程(Process),线程(Thread)等,他们都是内核对象。这些内核对象虽然通过不同的系统 API 来创建,但这些 API 都有一个共同特点,就是都需要传入SECURITY_ATTRIBUTES安全描述符结构体指针,并且返回句柄(HANDLE)。依据这个特点,我们有一个简单方法来判断对象是否是内核对象,就是看创建它的函数是否允许传入SECURITY_ATTRIBUTES安全描述符。

阅读全文 »

C++自 C++11 起支持 static_assert 编译时断言,如:

1
2
static_assert ( bool_constexpr , message )		(C++11 起)
static_assert ( bool_constexpr ) (C++17 起)

如果编译器不支持 C++11(经测试 VS2010 已经支持static_assert),我们可以使用下面方式来实现编译断言:

1
#define COMPILE_ASSERT(expression) switch (0) {case 0: case expression:;}

使用方法:

1
COMPILE_ASSERT(1 != 1);

上述方式虽然能实现编译断言,但缺点也很明显:

  • 错误提示信息的可读性较差;
  • 表达式必须是一个编译期常量表达式;
  • 无法使用在模板元编程中。

强烈建议拥抱新标准,使用 static_assert,做一个开心的人!

运行时库(Runtime library)通俗的说就是我们的程序运行的时候所依赖的库文件。在 Windows 平台,这些库由微软提供,称之为 Visual C++ 运行时库,虽然叫 C++ 运行时库,但也包含了 C 运行时库。

这些库以两种形式被提供:静态库(lib)动态库(lib + dll),每个库还分别提供了 Debug 和 Release 两个版本。

阅读全文 »

常见图形编程接口

我们常见的图形编程接口主要分为如下派系:

  1. OpenGL
  2. DirectX
  3. Vulkan
  4. Metal

下图展示了各个派系的分支及特点:

阅读全文 »
0%