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 两个版本。

阅读全文 »

dpi 是“Dots Per Inch”的缩写,表示每英寸的像素点个数,也就是像素点的密集度。

dpi不是用来表示屏幕分辨率的,也不是用来表示屏幕物理尺寸的。

阅读全文 »

常见图形编程接口

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

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

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

阅读全文 »

中文手册

这这里分享几个我一直使用的 NSIS 中文手册:

  • 《NSIS 用户手册 中文版》

    NSIS 官方英文的手册上的机器翻译版本,有些地方翻译可能不太纯正。

  • 《NSIS 图文教程集锦 - 轻狂志》

    里面有很多基于 NSIS 的安装包示例,大多数与 NSIS 有关的功能,都可以在这个文档找到线索。

上述文档下载地址:
https://github.com/winsoft666/NSIS-Chinese-Doc

UI插件

介绍一个我开发的开源NSIS UI插件 NSIS-UI-Plugin,基于 NSIS-UI-Plugin 插件我们可以快速使用NSIS制作类似QQ等软件那样的安装包。

该插件默认使用Qt作为界面库(不需要编译Qt静态库,可以使用Qt动态库),但也可以很方便的切换使用其他界面库,如DuiLib等。

项目地址:

https://github.com/winsoft666/NSIS-UI-Plugin

使用NSIS-UI-Plugin插件需要提前安装如下工具。

NSIS

https://nsis.sourceforge.io/Download 下载NSIS并安装,新增系统环境变量NSIS_DIR为NSIS安装目录。

Python

之所以需要安装Python,主要是为了执行NsisScriptGenerate.py脚本。

Python.exe所在目录添加到Path环境变量。

Qt

因为插件默认使用Qt作为界面库,所以需要安装Qt。

Qt安装包会默认将安装目录添加QTDIR环境变量,如果没有自动添加,则需要手动添加。

开始使用

编译NSIS-UI-Plugin

安装完上面依赖项之后,编译NSIS-UI-Plugin\NSIS-UI-Plugin.vcxproj工程,Visual Studio的生成后事件会自动将目标文件(Debug版:nsQtPluginD.dll, Release版:nsPlugin.dll)拷贝到NSIS插件目录(NSIS_DIR\Plugins\x86-unicode)。

生成安装包

VimeoSetup是一个关于如何在NSIS中使用该插件的示例工程:

1
2
3
4
5
App                -- 放置需要打包到安装包中的文件
VCRuntimeDLL -- 放置VC++运行时库文件(Debug版和Release版),Qt界面库默认采用MD模式编译,运行时需要依赖VC++运行时库
vimeo-template.nsi -- NSIS模板文件,文件名的`-template`后缀固定的,NsisScriptGenerate.py会根据该模板生成vimeo.nsi
build-setup [debug].bat -- 生成Debug版的安装包,即使用Debug版的Qt和NSIS-UI-Plugin
build-setup [debug].bat -- 生成Release版的安装包

将需要打包的文件放置到App目录,然后运行build-setup.bat生成安装包。

NsisScriptGenerate.py脚本功能:因为NSIS没有提供获取文件释放进度的功能,所以NsisScriptGenerate.py遍历App目录,采用File命令挨个添加文件,并调用插件接口SetInstallStepDescription通知安装详情。

截图

仅用作示例,你可以使用任意界面库来创建任意的安装/卸载界面。

在正常情况下安装包会有“欢迎界面”、“安装目录选择界面”等等,有时我们需要安装包自动跳过这 2 个界面,如安装包通过命令行参数传入“安装目录”(如setup.exe /installdir F:\test),本文讲述如何使安装包跳过指定的界面。

阅读全文 »
0%