现在还有多少人做 C++跨平台移动开发?

2019-11-23 11:25:18 +08:00
 cyxcw11
我们部门现在想用 C++做跨平台移动开发,底层业务逻辑用 C++写,上层 UI 源生。
大家有类似的经验么?有多少坑?
12396 次点击
所在节点    C++
64 条回复
heiheidewo
2019-11-24 08:54:38 +08:00
在大厂做这块几年了,上层接口逻辑和 UI 用原生语言( oc/java,windows 上随便用哪个都可以),底层 C++,目前是 4 个平台:Windows/Mac/iOS/Android。
如果要给用户提供 sdk 或者用到第三方 sdk 的话,需要注意 iOS 下的符号冲突问题( c++就改命名空间,c 的话自己写脚本对静态库符号进行重命名,这个是巨坑,挺恶心的。
客户端还需要考虑体积和性能问题。

暂时还没发现有别的靠谱方案
ww2000e
2019-11-24 09:12:46 +08:00
Dropbox 前阵子才放弃 c++开发移动端,另愿开发两套代码
abcbuzhiming
2019-11-24 09:45:55 +08:00
本人作为一个从 windows 时代就开始编程的人,必须说跨平台付出的代价是巨大的,某些时候真的不是一套代码能解决所有的问题,所谓跨平台只适合你的业务并不是特别负责,对目标平台的原生功能应用不多的情况下,特别是项目初期,跨平台的初期收益能超越复杂度带来的代价,但是随着项目稳定,时间越长,跨平台带来的技术难度代价会超越“一套代码”带来的收益,这也是为啥凡是能活下来的大型 App 最后还是走了分化的,一个平台一套代码的道路
missdeer
2019-11-24 14:10:30 +08:00
@rainymorn iOS 的 app store 不允许动态链接非系统的库
paoqi2048
2019-11-24 14:22:52 +08:00
基础类库跨平台就行了,业务逻辑不推荐
FrankHB
2019-11-24 15:32:52 +08:00
@cyxcw11 理想情况下,C++ 的技术优势是一坨屎。重复重点,“一坨”屎。因为这种涉及移动平台的开发普遍缺乏标准化,基本上你用几个 native 方案就是几坨屎(语言、框架甚至开发工具都不怎么通用),充其量就是比 C++的屎小那么点;但只要是超过一坨,工程上的复杂性就超过一坨两倍以上;而且因为可以公开使用的资源可能不够丰富的问题会恶化;实际要正经考虑跨的平台不止两个,那就经常不止两坨;种种原因综合下来,高下立判。
然而非技术问题上的渣滓对一般来讲更麻烦。首先,C++ 糊的屎的粘度经常不够大,就算是自己造的,不专门安排人去“优化”框架本身的话,一不小心就散了,结果碎片化方案的数量上比直接用 native 的更恶心。然后,C++ 的用户素质比起现有 C++框架方案设计本身普遍还要低下,你招得到能 hold 住现有方案的人,那就是在赌脸。
和 @xsen 说的有点不同,这里 hold 住还不够,要保证框架维护人员能跟得上产品生命周期,否则万一人员流失交接起来会非常困难,规模一大会很快没法收拾,于是其实还得有足够强力的备胎开发人员才安稳……所以实力不够养的起闲人(乃至自己搞整个跨平台方案的)项目组基本就只能被迫放弃整坨 C++ 屎了。
尴尬的是,有些地方现实可行角度上还是非得用 C++ 不可,于是流行 C++ 写这种不得不用的所谓“关键”模块。所以你会见到这种大杂烩,其实就是工程上的妥协。(另一个角度上说,真能强行拿 C++ 硬肛的那确实算是有点实力的,虽然经常不能算是经济上的最优方案,质量也经常不咋地。)
而具体妥协的效果能怎么样,真没法一概而论,不光和人员素质,和开发内容(比如说现实不得不用 C++ 的模块占比)也有关。你还是得问问你老板能给多少预算和承受多少项目失败的风险再决定。
再具体来讲,如果你是要开荒自己造平台甚至造生态,那么一开始就上 C++ 之外,基本没什么别的选择(除非你自己能花几年做出汇编器编译器之类的全套工具链,像 Chez Scheme + Racket 这样;至于 C,会搞这个的更难找,别多想了)。
而如果只是要开发应用,那么方案余地会松一些。特别地,只限定 Windows/Linux/macOS/Android/iOS 这几个常见平台中的个别几个的话,可能还有不少别的选择。只是很遗憾,现时如果你打算通吃这些平台并执意避免分别重复开发不同的 native 实现,现成的方案里大概可能就只有 Qt 能马上上手——效果看着办,不大容易比用 native 的好。
关于 Qt 多提几句:
1.开发新平台的话,要是不考虑成本没项目周期限制,自造的肯定能有更大的余地。定制 Qt 是小的嵌入式平台的备胎选择,理论上确实也算是 Qt 的卖点之一,实际上嘛,呵呵……
2.话说回来,Qt 的 GUI 其实还算 Qt 里质量相对过得去的(尽管其实现的绝对质量不咋地,GUI 实现这部分隐藏了尤其多的外行人难以摆平的恶心的细节,相对质量一般总比临时赶工自己造的轮子好),所以要用 Qt 放弃还里面的 GUI 某种程度还是有点浪费的;而只是做业务框架,其实并不见得比有经验的自己搭框架好。
3.QtCreator 是能用,但主要只是跨平台统一环境有优势,实际体验谁用谁知道。如果你是 PM,建议别限制开发人员的环境(反正都跨平台了……)。同时,对上规模的项目,为了分散上游选型风险,需要考虑采取措施避免过于依赖 Qt-specific 的(特别是和别家 C++ 习惯都太不一样的)技术。
(我现在没维护多少用 Qt 项目的代码,但我为了自己造能代替 Qt 的备胎,主流 C++ 框架多少都看过,而且改过若干 W 行用 Qt 的开源代码自用,所以可修改性问题有多屎的参考意见……看着办。)
shuangya
2019-11-24 15:38:23 +08:00
还是分情况吧
[小型项目]
你爱用什么都可以。
[大型项目]
不知道楼上各位公司体量和 Slack、Dropbox、Alibaba 等公司比起来怎么样?
是大厂招不到能 hold 住 C++跨平台、能“把握框架与方向”的人吗?
是大厂只能招到对 C++“一知半解”的人吗?
是大厂觉得钱多了,放弃掉“成本更低”的跨平台方案,选择“成本更高”的原生方案吗?
目前大厂中最多的情况依然是:上层 UI 用原生或者 JS 跨平台实现,底层每个平台一套代码。这套代码可以是 C++,但一般不会是一套代码全平台共享。
为什么? C++跨平台初期可以让团队尝到“甜头”。但是项目一旦慢慢变大,随着业务扩张、底层深入、人员变动,“跨平台”的代码也会逐渐变得越来越难维护。
FrankHB
2019-11-24 16:35:31 +08:00
@abcbuzhiming 结论上我同意这位说的。
不过到这个份上,所有在这楼里提到问题的其实还只是冰山一角……能只考虑单一项目的问题而不是更长期的副作用,实在是很幸福的了。一方面,做项目会遇到选型问题;另一方面,维护个人技术栈也是很坑的。
虽然和主题没有直接的关系,我在这里想多补充一点生态而不是方案上的牢骚:造成现在的混乱的原因,虽然算不上是有意的,但过于放纵 naive 的 native 方案的开发者多少都有历史责任。
首先,业界公认的一些基础方案的可移植性实际是非常强的,远远超过在个别指定平台中选择可行方案的跨平台需求,但欠缺足够多的用户去鸟,造成形同虚设,还要在标准化上倒贴维护成本。
像 ISO C 从一开始就强调 portability,强到了绝大多数应用开发者匪夷所思的地步——比如 CHAR_BIT >=8 ( 1 字节可以大于 8 位),比如整数的表示可以源码补码反码之一,比如 '0' ~ '9' 执行字符集要求编码连续但 'A' ~ 'Z' 就不是……
一方面这些差异因为几乎从来没什么开发者去纠结而默认了—— POSIX 和 Win32 以及常见体系结构都钦定 1 字节 = 8 位,几乎所有体系结构都要求机器数用反码,除了 IBM 的某些异类都要求 'A' ~ 'Z' 的编码连续……这样的一个结果就是大多数 C 的开发者其实只是使用了一个较弱可移植性的子集。而 C 的层次上,因为提供了这样强的可移植性,对实现的约束就非常弱,所谓 strictly conforming program 几乎就没什么实际的活能干。其实 C 的用户在这个意义上已经分裂了,绝大多数的人都在用 GNU C、POSIX C 或者 Win32 下的 MSVC 方言,外加一票嵌入式平台的魔改方言。另一方面,ISO C 又不可能把这些方言都吸收了,因为这削弱可移植性,跟 C 的设计者的意愿就有冲突,也会引起不同厂商之间不可调和的矛盾。这就是一个长期没人能解决的两难状况。
ISO C++ 因为 C++ 的复杂性这样的一坨屎的情况,比 C 总体好得多(虽然 C++ 的乱加特性还导致另外的问题),比如干脆直接回避了 strictly conforming program 的概念。不过大部分 C 的可移植性包袱包括用户脱离语言 spec 的认知的问题也还是继承了下来(如大部分用户可能都不知道直到 C++20 才刚刚要去除除了补码以外的机器数的支持)。这样长期下来的结果就是 C++ 和 C 用户一样具有强烈的碎片化倾向,而标准语言长期不够用又反过来让不可移植的小圈子扩展更加猖獗继续加剧碎片化(如 Qt 的 moc )。加上非通用工具使用经验的依赖,进一步大幅提升招人的成本。
对关心以后业界发展的生态用户来说,这一直是两难问题。一方面不能否认 Qt 这样的(相对标准 C++ )半吊子扩展方案确实解决了标准语言不便搞定的不少问题;另一方面,越是依赖 Qt 这样的方案,越是没有办法阻碍分裂,以至于以后越来越不可能有标准化的跨平台方案能用(直接的原因:人员和工具成本越来越高)。
所以在选型的立场上我也是两难的态度:一方面用 C++ 这样的基础方案本身已经在承受无法彻底解决问题的困难;另一方面,足够大的项目中不去用 C++ 这样的单一基础方案而分别重复造轮子的选项,多出来的开销迟早会让你无法自拔。
WG21 已经认识到这里的问题的严重性了,所以才强推不适合在语言 spec 里搞定的 module 之类的东西,以便加强 tooling。不过技术上这种强行乱来我是不看好,该无视的还是无视吧。
(至于 C/C++ 最终是靠什么才在一片混战下活了下来?山中无老虎猴子称大王+历史包袱。)
其次,有不少大企业想建立生态填补这里的矛盾,但实际上技术上都失败了,败给了 C/C++ 的历史包袱。
考虑现在应用的技术栈,操作系统(是个大坑)先不提,光是运行时的实现,只要有些定制需求,就不可能彻底甩脱这个包袱。比如,各种服务器语言的运行时不是 C 就是 C++ 实现的;最终用户碰到的 web agent 几乎无一例外都是 C++ 实现的。结果就是你逃离 C/C++ 完成常规的开发基本还算可行,但一旦要“调优”,就得多少储备这些实现上的细节。然而运行时基本都不是自己开发的……谁能保证这样的任务总是能够被解决?(于是有的企业干脆就自己定制语言实现了,但还是一种循环。)
好在大部分项目在接触到这个坑之前,业务上可能就已经自然死了。但万一没死……恭喜你又制造了一坨业界历史包袱……
苦中作乐的话这也不全是坏事:恶心的屎全归结到 C/C++ 以后,C/C++ 就是屎的事实上的金标准,甚至在没有具体厂商撑腰的前提下就可以避免 vendor lockin。比如听说某果想仗着 ObjC 搞垄断?没关系,你 ObjC 糊弄多少新的开发者也没 C/C++ 的历史包袱和群众基础,只要能糊得上,就算没 native 程度的支持是会恶心到大多数开发者,但谅你也不敢彻底不支持,否则就是自寻死路。(相比之下,web 自己作另说,搞图形学什么的就有点惨了。)
最后,作为历史包袱的受害者能怎么做?
横竖都不咋地,如果没法改变所谓的生态,自求多福,祈祷不会遇到意外吧。
如果谁真能在业务以外实际推动跨平台的实践,我姑且代表个人表示感谢。不过我是真不太信整个蓝星人都不太搞得好的问题,一般人能不添乱的。能尽量别依赖并且能适当抵制不靠谱的半吊子 native 方案就不错了。
请量力而行。
FrankHB
2019-11-24 16:39:46 +08:00
草,一坨错别字……
“源码反码补码”→“原码反码补码”
“几乎所有体系结构都要求机器数用反码”→“几乎所有体系结构都要求机器整数用补码”
icylogic
2019-11-24 16:44:41 +08:00
按照当时 Dropbox 的博客和后续的评价,他们的问题其实在于能搞定 C++ 框架的人跑了,现有团队 C++ 水平一般,而且看起来有些方向搞错了。

例如,他们提到的几个自己搞的库:

- json11 (为 c++11 开发的 json 库)

和 nlohmann/json , rapidjson 等比起来简陋太多了。这个库从 2013~2014 年开始在 GitHub 上维护。C++ 的 Serialization 库多如牛毛,json 库是打架最厉害的地方,不知道他们怎么想的要自己搞。

- 一套跨平台的 C++ 构建工具
"Most importantly, we needed a custom build system that created libraries containing C++ code as well as Java and Objective-C wrappers and could generate targets that were understood by both Xcodebuild and Gradle."
这种东西根本不是一个小团队能填完的坑……

跨平台里 C++ 应该承担的任务,我觉得 reddit 一个用户就说得很好:

> Slightly puzzled here, as it is not clear as what the scope of that C++ library is.

> I would expect dropbox to have a C or C++ cross platform library for its core behaviour (file content hashing, meta-data handling, sync configuration, thumbnail generation, indexing and searching, profile management, networking, caching, renaming, etc), and have it used on mobile and desktop platforms.

> Anything on top of that, like the model behind the mobile views, or the navigation logic, would be done in the native environment.

> From the look of it, it seems to me that they tried to implement pieces of the logic behind the UI of the mobile app in C++, and that isn't such a good idea. But I hope they didn't end up redoing all the core logic locally, that would be a waste.

> But still puzzled at the idea that the code that sync files may not be the same on all platforms...

https://www.reddit.com/r/cpp/comments/cqft4t/dropbox_replaces_c_with_platformspecific_languages/

在我看来,dropbox 这件事的意义在于告诉我们哪些地方尝试用 C++ 造轮子是坑,而不是“再也别考虑在任何跨平台应用里用 C++”. 不止是 UI 不应该跨平台写,所有不方便统一的 Native API 也要避免(例如它提到的“应用唤醒后台任务的 API”),这个不算 UI,但 platform-specific 的事情无论如何你也得写两遍,区别无非是 (Java/Kotlin 写一遍+ ObjC/Swift 写一遍) vs (用 C++ 写两遍然后用很难看的 macro/脚本 区分开),前者毫无疑问会更清晰且更好调试。
FrankHB
2019-11-24 17:09:34 +08:00
@icylogic 这里有些细节问题其实不太好一概而论。我是指,关于 platform-specific UI。
对有意造轮子的 team 来说,实际上他们的产品本身已经就是框架了。如果 hold 不住当然应该放弃,但如果 hold 得住呢?
须知,native 的 GUI API 的设计大多真的是挺不咋地的。
如 Win32 API 的基于 HWND 的 GUI 部分,就普遍比之后所谓 DirectUI 设计得要烂( Win32 API 烂的不止是整体风格问题,还有各种莫名其妙的随 API 版本碎片化的变通,比如子窗口半透明什么的)——其实后者才是应该正经设计的 API 的基本思路(乃至于我认为 DirectUI 这个词就不应该出现,因为所谓 DUI 就该是天生正常的套路)。
这个意义上,尽量依赖 native API 的 wxWidget 就比自造轮子的 QtWidget 靠谱,因为后者是方法论上更正常的原本就应该采用的设计。(这不限 C++ 。类似地,WPF 就比 WinForms 更自然。)
更进一步讲,我认为 C++ 这样的静态语言的普遍上不适合搞定通用 GUI 的任务。这个意义上,用 C++ 可能整体上就是历史习惯导致的错误选型。Web 在这方面就纠正了一部分,但还是相当地半吊子了。而移动端的玩意儿,我是不指望更干净。
水平比较,Win32 的 GUI 其实还算是 C/C++ API 里设计得比较好的了。(比起 X11 的一团混乱以及各种 CAD 之类的扩展 API 什么的惨不忍睹的玩意儿来讲的话。)
然而不踩过更烂的屎坑又没本事刷新自己技术栈的用户,可能用过一种 native GUI 就被这样套牢了,一旦换个底层技术栈就难以复用人员。这比项目维护本身可能还要命。
这样看,足够大的项目可能还不如一开始就如造 WPF 一样最小化跨平台兼容层的轮子了。
FrankHB
2019-11-24 17:19:16 +08:00
草,写反了,,“尽量依赖 native API 的 wxWidget 就比自造轮子的 QtWidget 靠谱”→“尽量依赖 native API 的 wxWidget 就不会比自造轮子的 QtWidget 靠谱”……
TangMonk
2019-11-24 18:49:17 +08:00
Pascal 也可以
owt5008137
2019-11-24 20:06:24 +08:00
我们游戏的战斗引擎是 C++, 然后渲染是游戏引擎
xuyuheng0905
2019-11-24 23:42:09 +08:00
我做了两年多的 C++跨平台底层+Native UI 的(大型)客户端开发。迭代速度是很快。对人的要求比较高(需要熟悉不同语言的坑)。国内的某钉好像也是这种架构。
urmyfaith
2019-11-25 09:11:45 +08:00
入坑 QT 中

感觉怎么说呢, 坑蛮多的.

入手成本高,维护成本也高.

很多问题都是 plantform-specic

遇到问题解决问题起来没有原生快.
shuangya
2019-11-25 12:28:26 +08:00
@xuyuheng0905 钉钉用的是 CEF……底层逻辑是两套……UI 是混合 Native 和 H5 的……
xuyuheng0905
2019-11-28 01:27:07 +08:00
@shuangya 移动端也是?
xuyuheng0905
2019-11-28 01:43:26 +08:00
@shuangya 要分情况讨论。CEF 在 Windows/Mac 比较适合,但也只是业务实现的形式罢了。说白了就是个皮。通用模块用 C++开发的跨平台库,是在于模块复用 /维护 /性能等多方面考虑的结果,还是值得讨论和尝试的。
missdeer
2019-11-28 14:26:51 +08:00
@shuangya
@xuyuheng0905
现在聊天软件的对话界面用 HTML 是一大流行趋势

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/622359

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX