跨平台 C++ 开发实战
跨平台 C++ 开发实战
C++ 跨平台开发涉及编译链接、文件系统、并发编程、数据库访问、网络通信、移动端开发等多个技术领域。本文汇总了 C++ 工程开发中的实用技巧,涵盖 GCC 链接配置、C++17 新特性、ORM 框架、HTTP 客户端、Android NDK 开发、JNI 编程、Go 交叉编译等核心主题,帮助开发者高效应对跨平台开发中的常见问题。
[图片占位符:C++ 跨平台开发技术栈]
一、GCC 静态链接与动态链接
# 默认动态链接gcc-oapp main.c-lmysqlclient# 静态链接指定库gcc-oapp main.c -Wl,-Bstatic-lmysqlclient-Wl,-Bdynamic-lpthread-ldl# 静态链接 stdc++gcc-oapp main.cpp -static-libstdc++注意:使用
-Wl,-Bstatic后必须恢复-Wl,-Bdynamic,否则后面所有库都会用静态链接。
二、C++17 filesystem
#include<filesystem>namespacefs=std::filesystem;// 检查文件是否存在fs::exists("/tmp/test.txt");// 遍历目录for(auto&entry:fs::directory_iterator("/tmp")){std::cout<<entry.path()<<std::endl;}// 创建目录fs::create_directories("/tmp/a/b/c");编译时需要链接
-lstdc++fs(部分 GCC 版本需要)。
三、读写锁(shared_mutex)
#include<shared_mutex>typedefstd::shared_lock<std::shared_mutex>read_lock;typedefstd::unique_lock<std::shared_mutex>write_lock;std::shared_mutex smutex;// 读操作(多个线程可同时获取读锁){read_lockrlk(smutex);// 读取数据}// 写操作(只有一个线程能获取写锁){write_lockwlk(smutex);// 修改数据}四、ODB ORM 框架
ODB 是 C++ 的 ORM(对象关系映射)框架,可以不写 SQL 语句直接操作数据库:
#pragmadbobject(person)classperson{public:#pragmadbmember(id_)idconststd::string&name()const{returnname_;}voidname(conststd::string&name){name_=name;}private:std::string name_;};注意:成员变量必须要有公共访问接口,且命名有规则(如
name_对应name()和name(const std::string&))。
五、libcurl HTTP 客户端
#include<curl/curl.h>curl_global_init(CURL_GLOBAL_DEFAULT);// 同步方式(easy)CURL*easy_handle=curl_easy_init();curl_easy_setopt(easy_handle,CURLOPT_URL,"http://example.com/api");curl_easy_perform(easy_handle);// 异步方式(multi)CURLM*multi_handle=curl_multi_init();curl_multi_add_handle(multi_handle,easy_handle);intrunning;curl_multi_perform(multi_handle,&running);curl_global_cleanup();六、二进制转十六进制
std::stringbin_to_hexstr(uint8_t*bin,std::size_t length){std::stringstream ss;std::for_each(bin,bin+length,[&ss](uint8_tch){ss.fill('0');ss.width(2);ss<<std::hex<<static_cast<uint32_t>(ch);});returnss.str();}七、STL resize 与 reserve 的区别
std::vector<int>v;// resize:改变 size,多出的元素会被初始化v.resize(10);// size 变为 10,元素初始化为 0v.resize(5);// size 变为 5,多余的元素被销毁v.resize(8,42);// size 变为 8,新增元素填充 42// reserve:改变 capacity,不影响 size,不初始化v.reserve(100);// capacity >= 100,但 size 不变记忆:resize 和 size 相关,reserve 和 capacity 相关。
八、MinGW-w64 工具链
MinGW-w64 是 Windows 平台的 GNU 工具套件,包含 gcc、g++、gdb 等:
三大 MinGW 发行版的区别:
| 发行版 | 说明 |
|---|---|
| MinGW | 最早诞生,只支持 32 位,不推荐 |
| MinGW-w64 | MinGW 的独立分支,支持 32/64 位,推荐使用 |
| TDM-GCC | MinGW-w64 的打包版 |
安装时注意选择正确的平台:i686为 32 位,x86_64为 64 位。
九、Android NDK 开发
给 Android 编写 C++ 动态库有两种方式:
方式一:使用 Android Studio + NDK
- 优点:可以调试 C++ 代码
- 缺点:NDK 占用空间大
方式二:使用 Linux NDK 交叉编译
- 优点:CMake 支持好,不占用本机空间
- 缺点:不能调试
关键 CMake 参数:
cmake..\-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake\-DANDROID_ABI=armeabi-v7a\-DANDROID_PLATFORM=android-23十、JNI 编程要点
JNI 是 Java 调用 C++ 的桥梁,核心流程如下:
- 创建 Java 类,声明
native方法 - 使用
javah生成 JNI 头文件 - 在 C++ 中实现 JNI 函数
JNI 函数命名规则:
Java_包名_类名_方法名// JNI 函数实现示例extern"C"JNIEXPORT jstring JNICALLJava_com_example_myapplication_MyDll_stringFromJNI(JNIEnv*env,jobject/* this */){std::string hello="Hello from C++";returnenv->NewStringUTF(hello.c_str());}JNI 开发要点:
- 强烈建议用
javah生成 JNI,不要手写 - Java 中通过
System.loadLibrary("native-lib")加载 SO 库 - SO 文件名要去掉
lib前缀和.so后缀
十一、Go 交叉编译与 CGO
当 Go 项目使用 CGO 调用 C++ 库时,交叉编译需要配置对应平台的 GCC:
# 编译 32 位程序setGOARCH=386setCGO_ENABLED=1setCC=i686-w64-mingw32-gccsetCXX=i686-w64-mingw32-g++# Linux 下通过环境变量指定链接库CGO_LDFLAGS="/usr/lib/libssl.a /usr/lib/libcrypto.a"go build main.go注意:
libssl.a和libcrypto.a的链接顺序不能乱。
十二、VS 中文编码问题
Visual Studio 默认使用 GB2312 编码,建议统一使用 UTF-8:
项目属性 -> C/C++ -> 所有选项 -> 附加选项 -> 添加 /utf-8/utf-8相当于同时设置/source-charset:utf-8和/execution-charset:utf-8。
总结
跨平台 C++ 开发需要掌握的技巧非常广泛,以下是需要重点关注的领域:
| 技术领域 | 关键要点 |
|---|---|
| 编译链接 | 理解静态/动态链接的区别,正确使用链接选项 |
| C++17 新特性 | filesystem 简化文件操作,shared_mutex 支持读写锁 |
| 数据库访问 | ODB 提供 ORM 能力,避免手写 SQL |
| 网络通信 | libcurl 支持同步/异步 HTTP 请求 |
| 移动端开发 | Android NDK 交叉编译 + JNI 桥接 Java 与 C++ |
| 跨语言调用 | Go CGO 实现 Go 与 C++ 的互操作 |
| 编码规范 | 统一使用 UTF-8 编码,避免中文乱码 |
跨平台开发的核心原则是:尽量使用标准库和跨平台框架,将平台相关代码隔离到独立模块中,通过 CMake 等构建工具管理不同平台的编译配置。
