CMake构建学习笔记20-iconv库的构建
1. 构建
iconv是一个用于在不同字符编码(如 UTF-8、GBK、ISO-8859-1 等)之间进行转换的开源库。笔者在《c++中utf8字符串和gbk字符串的转换》这篇文章中介绍过如何在Windows下实现utf8字符串和gbk字符串的转换,不过该实现是基于Win32 API的,在其他平台中是无法使用的。如果需要跨平台,那么就需要使用iconv这样的库来统一实现。
不过麻烦的是iconv是GNU/Linux项目提供的库,不提供CMake的构建方式,以及原生的MSCV的构建方式。在Windows下的构建官方推荐使用MSYS2来进行构建。不过MSYS2构建出来的成果不一定能与MSVC构建的成果二进制兼容,而在Windows下还是使用MSVC的情况比较多。所以这就有点僵住了,只能寻求第三方的帮助。
这里笔者的解决方案是直接使用vcpkg。vcpkg是微软开发的C/C++跨平台开源库管理工具,试用了一下,感觉确实比以前进步很多,如果不是像笔者一样有自己的需求,完全可以都使用vcpkg来安装依赖库。
通过以下指令下载并安装iconv:
git clone https://github.com/microsoft/vcpkg
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg install libiconv:x64-windows
iconv就会安装在vcpkg的目录下,如下图所示:

iconv是个底层库,不需要其他依赖库,因此可以直接复制到笔者的仓库中使用,算是满足了笔者的需求。另外,不知道vcpkg的机制是什么,vcpkg确实也使用了cmake来构建,因为生成了cmake的配置文件,可以直接被CMake项目集成使用。最后,默认情况下vcpkg会检测环境内的VS,使用最高版本的VS来编译链接,构建的时候要保证与目标版本一致。
2. 示例
最后就直接给一个CMake项目调用刚才安装好的iconv库的示例吧。因为vcpkg在安装iconv的时候,也安装了相应的cmake的配置文件,所以可以直接在CMakeLists.txt集成,关键配置代码是:
# 项目代码设置为utf-8编码
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
message(">> using Clang")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
message(">> using GCC")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
message(">> using Intel C++")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
message(">> using Visual Studio C++")
add_compile_options("/utf-8")
else()
message(">> unknow compiler.")
endif()
find_package(Iconv REQUIRED)
# ...
target_link_libraries(${PROJECT_NAME} PRIVATE Iconv::Iconv)
注意,find_package要生效,需要保证CMake能够搜索到相应的库。如果是直接使用的vcpkg,那么需要将vcpkg集成到CMake搜索路径中:
vcpkg integrate install
如果是像笔者一样,是将iconv复制到自己仓库中使用,那么需要在CMake的内置变量CMAKE_PREFIX_PATH中增加自己的仓库路径(比如修改CMakePresets.json文件中CMAKE_PREFIX_PATH的配置)。
将utf8编码字符串转换成gbk字符串的代码示例如下:
#include <iconv.h>
using namespace std;
int main() {
// 原始 UTF-8 字符串
const char *utf8_str = "你好,世界!";
printf("%s\n", utf8_str);
size_t in_bytes_left = strlen(utf8_str);
char in_buf[1024];
strcpy(in_buf, utf8_str);
char *in_ptr = in_buf;
// 输出缓冲区(GBK)
char out_buf[1024];
char *out_ptr = out_buf;
size_t out_bytes_left = sizeof(out_buf);
// 打开 iconv 转换器:从 UTF-8 转换到 GBK
iconv_t cd = iconv_open("GBK", "UTF-8");
if (cd == (iconv_t)-1) {
perror("iconv_open failed");
return 1;
}
// 执行转换
if (iconv(cd, &in_ptr, &in_bytes_left, &out_ptr, &out_bytes_left) ==
(size_t)(-1)) {
perror("iconv failed");
iconv_close(cd);
return 1;
}
// 关闭转换器
iconv_close(cd);
// 获取实际转换后的长度
size_t converted_len = sizeof(out_buf) - out_bytes_left;
// 直接写入二进制字节到 stdout(不经过 printf,防止转码)
fwrite(out_buf, 1, converted_len, stdout);
return 0;
}
运行结果如下所示:
浣犲ソ锛屼笘鐣岋紒
你好,世界!
CMake构建学习笔记20-iconv库的构建的更多相关文章
- Ext.Net学习笔记20:Ext.Net FormPanel 复杂用法
Ext.Net学习笔记20:Ext.Net FormPanel 复杂用法 在上一篇笔记中我们介绍了Ext.Net的简单用法,并创建了一个简单的登录表单.今天我们将看一下如何更好是使用FormPanel ...
- SQL反模式学习笔记20 明文密码
目标:恢复或重置密码 反模式:使用明文存储密码 1.存储密码 使用明文存储密码或者在网络上传递密码是不安全的. 如果攻击者截取到你用来插入(或者修改)密码的sql语句,就可以获得密码. 黑客获 ...
- golang学习笔记20 一道考察对并发多协程操作一个共享变量的面试题
golang学习笔记20 一道考察对并发多协程操作一个共享变量的面试题 下面这个程序运行的能num结果是什么? package main import ( "fmt" " ...
- 【学习笔记】开源库之 - sigslot (在解决浅拷贝问题的基础上增加信号拦截功能)
前言说明 在文中<[学习笔记]开源库之 - sigslot (提供该库存在对象拷贝崩溃问题的解决方案)>已经介绍过 sigslot ,此文主要应用在实际的工作项目中时,发现会有拦截信号的需 ...
- iOS学习笔记16-数据库SQLite
一.数据库 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等.离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式: 归档:NSKeyedArchiver 偏好设置:NSU ...
- SpringCloud学习笔记(6):使用Zuul构建服务网关
简介 Zuul是Netflix提供的一个开源的API网关服务器,SpringCloud对Zuul进行了整合和增强.服务网关Zuul聚合了所有微服务接口,并统一对外暴露,外部客户端只需与服务网关交互即可 ...
- 算法学习笔记(20): AC自动机
AC自动机 前置知识: 字典树:可以参考我的另一篇文章 算法学习笔记(15): Trie(字典树) KMP:可以参考 KMP - Ricky2007,但是不理解KMP算法并不会对这个算法的理解产生影响 ...
- Java学习笔记之使用反射+泛型构建通用DAO
PS:最近简单的学了学后台Servlet+JSP.也就只能学到这里了.没那么多精力去学SSH了,毕竟Android还有很多东西都没学完.. 学习内容: 1.如何使用反射+泛型构建通用DAO. 1.使用 ...
- [原创]java WEB学习笔记20:MVC案例完整实践(part 1)---MVC架构分析
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- Cocos2d-x 学习笔记(20) ControlButton
[Cocos2d-x 学习笔记 目录链接] 1. 简介 ControlButton实现了按钮功能,根据触摸的位置和移动的过程可识别9中EventType类型,执行对应的回调函数. 直接继承了Contr ...
随机推荐
- vue的a-tree-select选择父节点回显的是子节点
正常来说当选择父节点时候,我们回显的应该就是父节点的信息比如: 可是现在我想回显子节点的信息如何处理? 很简单:在 a-tree-select组件里面去掉这一句: 这样回显的就是我们想要的结果了 ...
- Review-Gate MCP,让你的 cursor request 次数翻 5 倍
最新资讯: cursor pro 改为无限制,但某些模型(新模型?)依旧限制,看起来是一个黑盒,具体没细说,因此你可以考虑装或者不装本文的 MCP. 另外,本文属于前端社区的一次分享,只是顺带迁移到个 ...
- AEM 与 ActiveMQ 集成方案详解
Adobe Experience Manager (AEM) 与 ActiveMQ 的集成可实现系统间的解耦和异步通信,以下是详细的集成步骤与代码实现: 一.环境准备 AEM 环境:AEM 6.5+ ...
- MobiSys'2022 CoDL论文详解
算子切分 在了解算子切分前,先了解一下卷积的运算过程,作者将算子切分分为了两个维度的切分:OC维度和H维度,没有W维度可能与数据在内存中的存储方式有关. OC维度切分 卷积就是OC数量个kernel_ ...
- laravel项目上传Linux服务器
第一次上传项目:记录一下遇到的问题!!! #1)工具:腾讯云服务器and域名(以解析) Xshell(强大的安全终端模拟软件) 链接:https://pan.baidu.com/s/1we6dw5ys ...
- C# 泛型对象转Get请求参数
/// <summary> /// 对象转Get请求参数 /// </summary> /// <returns>< ...
- iis6导出Excel报错检索 COM 类工厂中 CLSID 为 {00024500-0000-0000-C000-000000000046} 的组件时失败,8000401a错误解决办法
1:在服务器上安装office的Excel软件. 2:在"开始"->"运行"中输入dcomcnfg.exe启动"组件服务" 3:依次双 ...
- 前端开发系列014-基础篇之Javascript面向对象(三)
一.原型对象相关方法 ❏ in 关键字 ❏ instanceof ❏ hasOwnProperty方法 ❏ constructor构造器属性 ❏ isProtoTypeOf方法 in关键字 作用 用来 ...
- ble设备的第一次成功例子
http://www.cnblogs.com/vamei/p/6753531.html#undefined 参考博客 树莓派作为BLE外设 下一步,我们尝试用树莓派进行BLE通信.我们先把一个树莓派改 ...
- Codigger应用商店(Store):连接开发者与用户的功能平台
Codigger应用商店(Store)作为Codigger生态中的重要组成部分,承担着连接开发者与用户的桥梁作用.它构建了一套从开发创作到发布推广,再到价值变现的完整流程,为生态内的各方提供了协同互动 ...