专栏首页重归混沌移动平台native代码遭遇的坑

移动平台native代码遭遇的坑

最近客户端终于开始运行在移动平台上了,之前在PC平台上完全没问题的代码,开始出现一些诡异的问题。

为了保证客户端和服务器使用绝对相同的逻辑执行流程,我们采用C++来开发一部分native代码同时供客户端和服务端来使用。在迁移到移动平台时,这些native库在IOS和Android平台上出现了不同程度的水土不服。

首次在移动平台就发生了crash,并且只有Android平台会crash, 而IOS可以正常进入游戏。

最后定位到,当执行类似下面的代码时安卓平台就会发生crash。

int a = 3;
char buf[64];
char *p = buf;
*p = 0;
*(int *)(p + 1) = a;

在编译安卓平台native动态库时,为了尽可能的保证兼容性,我们采用了armeabi-v7a来编译native动态库,据ARMv7开发文档显示,在ARMv7架构下,uint32_t *需要4字节对齐,而uint16_t *则需要2字节对齐,只有uint8_t *才不需要对齐约定。

而苹果自iphone5s发行时,就采用了基于ARMv8-A架构的Apple-A7。根据ARMv8-A开发文档显示,在ARMv8-A架构下,所有地址访问都不再需要指针对齐要求。换句话说在IOS的64位平台上,上面代码是完全正确的。

当然,木桶原理,为了保证代码在所有平台上都能正常运行,需要做出如下修改:

//此段代码同时可以无视机器大小端,而强制a在内存中的布局为大端还是小端,此种写法为小端
- *(int *)(p + 1) = a;
+ p[1] = a & 0xff; 
+ p[2] = (a >> 8) & 0xff; 
+ p[3] = (a >> 16) & 0xff; 
+ p[4] = (a >> 24) & 0xff;

如果要保持与机器大小端相同可采用如下写法:

- *(int *)(p + 1) = a;
//由于a只有四个字节,此处可以手动展开memcpy以优化函数调用和for循环
+ memcpy(p, &a, sizeof(a));

看到Android这么热闹,IOS也有点不平衡,在调用某个native函数时,报出了`To marshal a managed method, please add an attribute named ‘MonoPInvokeCallback’ to the method definition.`错误。

但是并不是所有native函数都会有这个问题。经过比较发现,这个函数在设计时,为了方便方便Unity可以接管native内部的log, 多增加了一个参数,用来将C#中log函数传入。直接将参数改为NULL时,果然问题解决了。但是很奇怪的是,在Windows下并不会有此问题。

最终在MonoTouch的官方文档中找到了答案。

在微软向ECMA提出的CLI(通用语言基础架构)中,并没有定义标签`MonoPInvokeCallback`。这也正印证了,我们在PC平台上从来没有出现过此问题。

如果在编译成移动平台时’Scripting backend’选项选用了`IL2CPP`,就需要使用AOT编译器来进行编译。

而进行AOT编译时,MONO需要知道哪些静态函数可能会被native代码调用,以便对C#函数进行额外处理(ps. 理论上,一个函数是否需要会被传入native函数中,是可以在编译时推导出来的,不知道MONO为什么没有做这件事)。

本文分享自微信公众号 - 重归混沌(findstrx),作者:重归混沌

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-10-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • DC3算法

    最近做了一个差量更新工具, 实质就是一个Diff工具。这个Diff工具在本地生成一个patch文件。客户端通过网络下载到本地后,根据本地文件和patch文件来生...

    重归混沌
  • 双向链表的三种实现

    这篇文章,其实很像是“茴字的四种写法”。这让人不由的想起来孔乙己。在我印象中,大多数人对孔乙己是持嘲讽态度的。

    重归混沌
  • 谈谈Unity的资源管理

    在Unity最佳实践明确指出, 要使用AssetBundle而不是Resources目录来管理资源。

    重归混沌
  • JavaScript 标准内置对象Promise使用学习总结

    .catch将在new Promise时定义的匿名函数执行失败、.then函数执行失败,并且位于其后的then函数没有显示提供第二个参数(供失败时调用的函数)时...

    授客
  • Java 可变对象和不可变对象

    作者:幽鸿   Mar 14, 2016 10:21:27 PM

    幽鸿
  • Python反爬虫伪装浏览器进行爬虫

    对于爬虫中部分网站设置了请求次数过多后会封杀ip,现在模拟浏览器进行爬虫,也就是说让服务器认识到访问他的是真正的浏览器而不是机器操作

    砸漏
  • Java并发-10.等待/通知

    悠扬前奏
  • 理解SVM的三层境界(二)

    第二层、深入SVM 2.1、从线性可分到线性不可分 2.1.1、从原始问题到对偶问题的求解 接着考虑之前得到的目标函数: ? 由于求 的最大值相当于求 ...

    IT派
  • 爬虫必备技能之网页解析库:xpath用法和实战

    在安装 scrapy 之前需要先安装 Twisted 地址: https://www.lfd.uci.edu/~gohlke/pythonlibs/#twis...

    润森
  • 响铃:IP跨界她经济,同道能讲好“单身婚纱”的故事吗?

    国泰君安证券报告显示,女性消费对经济增长的贡献率接近70%,到2019年中国内地女性经济市场规模近将接近4.5万亿元,而家庭消费中,近75%由女性决策。

    曾响铃

扫码关注云+社区

领取腾讯云代金券