资源标识符的符号名称在头文件中定义,默认情况下是Resource.h。在源代码和资源脚本中,符号名称被预处理器替换为它们各自的数值。编译开始时,符号信息已经没有了。
要实现使用符号名称进行配置的方案,您必须提取并保留符号名称和资源标识符之间的映射以供以后在运行时使用,或者在部署之前将该映射应用于配置文件。以下是可能的选项列表:
使用关联容器并在应用程序启动时填充它:合适的容器是std::map<std::string, unsigned int>。使用 C++11 的 list initialization 功能可以方便地填充此容器:
static std::map<std::string, unsigned int> IdMap = {
{"ID_FILE_NEW", ID_FILE_NEW},
{"ID_FILE_OPEN", ID_FILE_OPEN},
// ...
}
在运行时,您可以使用此容器来检索给定其符号常量的资源标识符:
unsigned int GetId(const std::string& name) {
if (IdMap.find(name) == IdMap.end())
throw std::runtime_error("Unknown resource identifier.");
return IdMap[name];
}
这种方法的缺点是您必须保持IdMap 和资源同步。每当添加、修改或删除资源时,都必须更新容器内容以反映所做的更改。
解析 Resource.h 并存储映射: 包含符号标识符名称的头文件具有相当简单的结构。定义符号常量的代码行通常具有以下布局:
\s* '#' \s* 'define' \s+ <name> \s+ <value> <comment>?
提取映射的解析器并不像看起来那么难实现,并且应该在构建过程中的适当时间运行。提取映射后,可以将其存储在任意格式的文件中,例如INI file。该文件可以与应用程序一起部署,也可以作为资源编译到二进制映像中。在应用程序启动时,内容被读回,并用于构造上一段中描述的映射。与之前的方案相比,解析Resource.h文件不需要在资源变化时手动更新代码。
解析 Resource.h 并转换配置 XML 文件: 与之前的解决方案一样,此选项也需要解析 Resource.h 文件.使用此信息,然后可以转换配置 XML 文件,在部署之前用符号名称替换它们的数字对应项。这也需要额外的工作。但是,一旦完成,该过程就可以自动化,并验证结果以保持一致性。在运行时,您可以简单地读取 XML 并随时获得数字标识符。