如何在CMake中生成包含空字节(NUL byte)的字符串?
CMake: 解决十六进制字符串转回二进制文件的空字节问题
CMake里用file(READ <filename> <variable> HEX)把二进制文件转成十六进制字符串确实很方便,但反向操作就没那么直接了——毕竟file(WRITE ...)只是单纯写入字符串内容,没法直接把十六进制串还原成原始二进制。
我见过不少人尝试先把十六进制字符串拆成十进制数字列表,再用string(ASCII ${bytes} bytes)来转成二进制内容,但这里有个致命问题:一旦内容里有空字节(\0),CMake的string(ASCII)就会直接罢工,因为它会把空字节当成字符串的结束标记,导致后面的内容全部丢失。
那怎么处理这个问题呢?我写了个小的CMake函数来搞定它,核心思路是逐字节处理,绕开string(ASCII)的限制:
function(hex_to_binary hex_string output_path) # 先校验十六进制字符串长度必须是偶数,每个字节对应两位十六进制字符 string(LENGTH "${hex_string}" hex_length) math(EXPR remainder "${hex_length} % 2") if(remainder EQUAL 1) message(FATAL_ERROR "Input hex string has an odd length, which is invalid!") endif() # 初始化输出文件为空 file(WRITE "${output_path}" "") math(EXPR total_bytes "${hex_length} / 2") # 逐字节解析并写入 foreach(index RANGE 0 ${total_bytes}) if(index EQUAL ${total_bytes}) break() endif() math(EXPR start_pos "${index} * 2") # 截取两位十六进制字符 string(SUBSTRING "${hex_string}" ${start_pos} 2 current_hex) # 转大写避免大小写问题,再转成十进制 string(TOUPPER "${current_hex}" current_hex_upper) math(EXPR current_byte "0x${current_hex_upper}") # 用Perl风格替换直接写入单个字节,完美处理空字节 file(APPEND "${output_path}" [==[${current_byte}]==] USE_PERL_STYLE) endforeach() endfunction()
用法示例:
假设你已经通过file(READ "input.bin" my_hex_str HEX)得到了十六进制字符串my_hex_str,只需要调用:
hex_to_binary("${my_hex_str}" "restored_output.bin")
就能得到和原文件完全一致的二进制文件,包括其中的空字节。
这个方法避开了string(ASCII)的局限性,直接通过文件追加的方式写入每个字节,不管是空字节还是其他特殊字符都能正确处理。
内容的提问来源于stack exchange,提问作者Freddie Chopin
相关产品推荐
相关产品推荐

