千家信息网

C++跨平台开发遇到的问题有哪些

发表于:2024-11-30 作者:千家信息网编辑
千家信息网最后更新 2024年11月30日,这篇文章主要讲解了"C++跨平台开发遇到的问题有哪些",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"C++跨平台开发遇到的问题有哪些"吧!1. 字符编码
千家信息网最后更新 2024年11月30日C++跨平台开发遇到的问题有哪些

这篇文章主要讲解了"C++跨平台开发遇到的问题有哪些",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"C++跨平台开发遇到的问题有哪些"吧!

1. 字符编码

在我的开发环境,clang 编码默认是 utf8, VS 是 GB2312(代码页是 936),它们都兼容 ASCII。

假如代码文件中只出现英文,两端都可编译。假如代码中出现中文,文件编码为 utf8, iOS 编译没有问题,VS 会出现编译错误 error C2001。假如设置编码为 utf16, VS 编译没有问题,而 iOS 会出现编译错误 encoding is not supported。因此假如代码有中文,需要将源文件编码修改为 Unicode(UTF8 带签名)- 代码页 65001。

参见 vs编译 error C2001: 常量中有换行符 中文无法通过编译

另外假如包含中文字符串,直接读取使用,程序运行起来很容易出现乱码。类似这样的代码:

const char* str = "你好啊,世界";

想将 str 的文字在不同平台都显示正确,是不可控的。跨平台代码不应该使用中文,绝对不能用中文定义字符串再读取,更严格的甚至不能用中文写注释。假如要显示中文字符串,应该将其从程序中分离出来,写在一个 utf8 编码的配置文件中,再动态读取。

我们就碰坑了,我们本意是在导出一个 lua Api 的时候,自动生成对应的文档。有类似这样的代码:

ADD_METHOD_WITH_DOC(Context,nv12ToRGBPass, "获取颜色空间 nv12 到 rgb 的着色器程序","3.2","[Program](#program)", "program",0)

后来发觉在 Windows 上编译通过,iOS 编译不过。修改编码后, iOS 编译过了,Windows 上又编译不过。当两端都编译过了,但又乱码了。最后只好都写成英文,自动生成英文文档。

2. int8_t 和 char

在 VS 上,int8_t 实际上是 char 的 typedef,也就是说 int8_t 和 char 是同类型的。但是在 iOS 上,int8_t 和 char 是不同类型的。下列代码

printf("%d\n", (int)std::is_same::value);

在 VS 上输出 1,在 iOS 上输出 0。这刷新我认知,我一直以为 char 和 int8_t 是相同的。因为这区别,又踩坑了。

为了方便写 lua 导出,我们用了 LuaCpp 的库,里面有这代码

typedef LOKI_TYPELIST_15(bool, char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, float, double,std::string, luaObject, luatable, int64_t) SupportType;

这里定义了一个 Loki 的 typelist, 包含支持自动转换的类型。typelist 参见书籍C++设计新思维。

LuaCpp 基本都是模板代码,假如类型 T 属于 SupportType,就可执行自动转换的代码,不然就需要手写转换,假如没有手写转换,对于此类型 T, 就会直接崩掉。

这里的代码很老了,一直都运行正常。直到某个接口出现了 int8_t,于是 VS 上运行正常,iOS 上崩溃了。

同理,int8_t, uint8_t, int16_t, uint16_t 也需要注意。

类似的模板代码,最好还是乖乖地使用标准库中的 std::is_integral 吧。不要那么聪明自己手写 typelist 了。

3. __VA_ARGS__

__VA_ARGS__ 可用于不定参数的宏。但是它的行为在 VS 和 clang 上是有区别的。如下面代码

#include #define MY_PRINT(format, ...) printf(format, __VA_ARGS__)int main(int argc, const char* argv[]){MY_PRINT("Hello, World");return 0;}

在 VS 上可以编译通过。但在 clang 上确实编译失败,clang 编译器的 __VA_ARGS__ 不能展开 0 个变长参数的。写成

MY_PRINT("Hello, World, %d", 1);

才可以正确展开。为了展开 0 个参数,需要写成 ##__VA_ARGS__, 定义为

#define MY_PRINT(format, ...) printf(format, ##__VA_ARGS__)

参考 Variadic macros with zero arguments

4. 跨 dll 模块的静态变量

一个工程经常有多个动态模块。在 VS 上,动态模块为 dll 文件; iOS 上为 framework 或者 dylib。VS 在跨模块时,默认符号是不导出的。clang 默认符号都是导出的。

在 VS 上,当想在 A 模块中定义某个类或者某个函数,让 B 模块使用,就需要使用 __declspec(dllexport)__declspec(dllimport) 标明。通常会定义一些宏,比如。

#if defined(OF_WIN32) || defined(_WIN32) || defined(WIN32)#   ifdef MODULE_A_API_LIB#       define MODULE_A_API __declspec(dllexport)#   else#       define MODULE_A_API __declspec(dllimport)#   endif#else#   define MODULE_A_API#endif

之后需要跨模块使用的函数或者类写成

class MODULE_A_API TestClass {};MODULE_A_API void myfunction(int a, int b);

通常都没有问题,假如忘记写导出,就会链接错误。但一旦涉及到模板和静态变量,这种平台的差别,就会是个坑。

模板代码通常会直接写在头文件中,比如下代码。

// myheader.htemplate class TemplateClass {public:static std::string str;};template std::string TemplateClass::str;

在模块中,包含了头文件 myheader.h,就可以使用 TemplateClass 了。假如这时模块 A 使用语句设置 str 的值

TemplateClass::str = "Hello, World";

之后模块 B 读取 str 的值。

std::string str = TemplateClass::str;

在 VS 中,模块 A 和模块 B 虽然都使用 TemplateClass,但因为没有导出,实际是分离的两个类,他们的静态变量并不会共享。于是就是模块 A 设置了 TemplateClass::str,模块 B 读取的还是默认的空值。

而在 clang 编译器中,默认是导出的。于是模块 A 和模块 B 看到的是相同的 TemplateClass,静态变量是共享的。于是模块 A 设置了 TemplateClass::str,模块 B 读取的是设置后的 "Hello, World"

这种 Bug 比较隐蔽,可以正常编译,也可以运行,但实际结果就是不对。我们就踩过类似的坑。

前文说过,我们使用了 LuaCpp 这个库来导出 lua。这个库是个模板库,它包含一些静态变量,用来实现自动注册。我们在模块 A 中注册了一批 lua 类。之后在模块 B 中往 lua 虚拟机压注册过的类对象,在 iOS 上运行正常,但在 Windows 上就异常。因为在模块 B 中看来,LuaCpp 的记录中,这些类根本就没有被注册过。

感谢各位的阅读,以上就是"C++跨平台开发遇到的问题有哪些"的内容了,经过本文的学习后,相信大家对C++跨平台开发遇到的问题有哪些这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

模块 代码 编译 问题 编码 中文 文件 C++ 开发 变量 模板 类型 静态 运行 字符 动态 参数 字符串 实际 就是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 北京手机服务器 奥的斯服务器快车教学视频 广州佳骏网络技术公司 成都金苍地软件开发工作室法人 qq空间如何增加服务器 服务器电源汽车 web服务器安装组件已经损坏 中国农业银行软件开发中心好吗 注重数字和网络技术的应用 铜陵电商软件开发哪家好 丰润java软件开发 钉钉机器人给服务器发送指令 服务器安全加固系统 ssr 桌面软件开发学什么编程语言 企业网络安全准入系统 宁夏大学数据库技术与应用 网络运维和网络安全哪个好 免费在线数据库设计工具 思科网络技术学院教程下册 物流信息数据库系统 拂晓胜利之刻无法连接服务器 数据库的高可用方法 血小板基因数据库官网 网络安全校园日发言稿 12月新能源汽车数据库 商洛网络技术联系方式 普陀区参考数据库销售收费标准 网络安全面临的各种问题 电竞酒店服务器必须要公网ip吗 服务器防火墙关闭
0