我怎么觉得 Java 的 JNI 比 Go 的 CGO 要好呢?

2022-06-12 23:45:57 +08:00
 thewiredguy
7242 次点击
所在节点    Go 编程语言
47 条回复
DefoliationM
2022-06-13 11:20:25 +08:00
@thewiredguy embed 打包到二进制里
lysS
2022-06-13 11:41:51 +08:00
@thewiredguy 喔,看叉屁了
hhaobao
2022-06-13 11:42:09 +08:00
@orzglory 谢谢, 这些我都知道的. 但我感觉还是说不通 cgo 是半残啊, 你有没有跟 jni 或者 python 调 c 的这些语言对比资料. 我学习一下其它语言在调 c 这块比 go 好在哪
icexin
2022-06-13 11:43:45 +08:00
跨语言调用 c 模块有其自身的复杂度在,不可能简单,也注定不是平凡的事情,任何语言都要面对。
主要有以下几个问题:
1. 包管理的差异,c 没有官方的包管理,所以库的管理完全看系统,或者团队的约定工具,如 cmake 等。go 其实可以跟 c 一起源码发布成一个 go 的包,见 https://github.com/mattn/go-sqlite3
2. 交叉编译,新的语言基本上都有很方便的交叉编译方案,甚至不需要(脚本语言)。而 c 的交叉编译工具链其实很复杂,搞过嵌入式或者搞过路由器的都知道我在说啥。
3. 数据类型的差异。这部分主要是内存布局的差异带来的。比如一个 c 的 struct 不一定对应着高级语言里面的一个 class 。go 在这一点上其实做的很好了,go 的一个 struct 基本上对应一个 c 的 struct 。指针的概念也跟几乎一致,除了算数运算。所以 cgo 几乎可以不加修改的直接引用 c 的头文件,以及传递 go struct 作为参数给 c 函数。
4. 内存管理的差异。c 是手动管理的内存,所有内存都要自己显式分配和释放。新的语言基本上都有自己的内存管理方案,即 GC 。这就带来了语言之间内存传递的问题,c 分配的内存不会被 go tracing ,go 的内存也不能被 c 手动释放,其他语言类似。
5. 并发模型的差异。这部分基本上是语言自带协程的独特问题。因为 go 里面的协程有自己的栈,而 c 基本上可以认为是操作系统的线程栈。这两者之间的差异会带来诸如 TLS 和栈切换的问题。

所以综合看来,除了第 5 点是 go 特有的,其他语言几乎都有类似的问题。go 引入 cgo 主要是为了解决复用已有的大量 c 库的遗产,不是和 c 无缝调用,混合编程,目前也就 c++做到了和 c 无缝衔接,但为了这个能力 c++也付出了很多代价,到现在还在打补丁。 软件工程没有银弹,作为工程师最主要的工作就是熟悉各个模块的脾性,对症下药,挑选最合适项目的方案,而不是强行套方案,最终不符合预期的时候骂骂咧咧。
zhuangzhuang1988
2022-06-13 11:44:24 +08:00
@ComputerIdiot 都不如.net 系, 就是关注度太低了
lysS
2022-06-13 11:56:01 +08:00
有头文件的时候 cgo 还行吧,中间可以自动生成 go 的类型、函数。而且 FFI 本来就属于是程序间的 api ,两个语言“揉得太碎”,肯定性能和代码可扩展性会受损
Nugine0
2022-06-13 12:18:33 +08:00
@icexin Rust/C++/Zig 都可以无缝调用 C 语言,都有无栈协程,手动(半自动?)管理内存,允许声明与 C 一致的内存布局。相比 C++,Rust/Zig 的包管理和交叉编译更方便。你说的这些问题在系统级编程语言中都有完善的解决方案。
Buges
2022-06-13 12:28:10 +08:00
@icexin cgo 我见到最多的诟病是开销问题,调个系统 API 还好,如果是 hotpath 那开销非常明显。
jni/cpython 之类的开销如何我倒是不清楚。
还有交叉编译可以用 zig 作为 CC 使用,能让 go/rust 在交叉编译含 c 代码的库时开箱即用。
Srar
2022-06-13 13:42:50 +08:00
上面各位提到的 cgo 开销问题可以用魔法缓解下

https://github.com/petermattis/fastcgo
32uKHwVJ179qCmPj
2022-06-13 14:00:20 +08:00
@icexin 24# 说的非常对,还有问题的建议细品层主的回复并应用到其他语言上进行对比
swulling
2022-06-13 14:04:43 +08:00
有条件还是建议隔离出 C/C++服务,单独提供 RPC 供调用,如果是本地调用可以用 Unix domain socket 。这样后续维护起来也简单。
THESDZ
2022-06-13 14:46:38 +08:00
建议 rpc ,担心性能可以考虑 grpc
https://github.com/hashicorp/go-plugin
fgodt
2022-06-13 15:40:39 +08:00
但凡用 cgo 写过实际大项目的 都应该不会再选 cgo 了
akaHenry
2022-06-13 22:12:14 +08:00
@hhaobao

我贴给你的 FFI 相关博客, 就是 rust 和 dart 通过 C ABI 跨语言通信啊? 怀疑你有没有认真看?

至于 Python 调用 C. 这完全不用讨论.
Python 社区, 大量的包, 都是 C 实现, 然后 binding 给 Python 使用.
这是 Python 性能优化的基本手段.

> 关于 FFI / C ABI 跨语言通信. 是双向的. ( C ABI 是桥)

上面很多讨论, 都假定是 Go 通过 cgo 来调用 C 代码. (注意, 还有反过来的场景)

rust/c/c++ 的 FFI 都是双向通信能力优秀.

说 CGo 是半残, 就是尽量不要用.

没有什么方案设计, 是非它不行的, 缺它不可.
没有什么方案设计, 是非它不行的, 缺它不可.
没有什么方案设计, 是非它不行的, 缺它不可.

非喜欢抬杠的, 你喜欢, 你就多用, 每个项目都用.
akaHenry
2022-06-13 22:15:58 +08:00
https://github.com/trustwallet/wallet-core

这个 c++ 项目, 实现了跨语言 binding 到多个平台 iOS, Android(通过 jni).

core lib 层跨平台场景, 选项只有 rust/c/c++. 不要走邪路.
akaHenry
2022-06-13 22:31:54 +08:00
我上面贴的 2 篇博客, 都不看的?

github.com/hhstore/blog/issues/242
github.com/hhstore/blog/issues/355


> rust + ffi + flutter 实践案例:

- https://github.com/AppFlowy-IO/AppFlowy
- 这个项目, UI 层使用 flutter, core lib 层使用 rust.
- 是非常现代的设计方案.


> FFI 库( rust + dart):

https://github.com/fzyzcjy/flutter_rust_bridge
https://github.com/rust-lang/rust-bindgen
https://github.com/google/autocxx
https://github.com/rust-qt/ritual
https://github.com/eqrion/cbindgen
https://github.com/getditto/safer_ffi


https://github.com/shekohex/flutterust
https://github.com/sunshine-protocol/dart-bindgen
https://github.com/brickpop/flutter-rust-ffi
https://github.com/TimNN/cargo-lipo
https://github.com/bbqsrc/cargo-ndk

https://github.com/dart-lang/ffigen


跨平台场景, 要注意其他语言的 FFI 基础设施建设(易用性 /成熟度). Go 完全没有可比性.

现在贴内容, 都要投喂到这种程度, 才看吗?
如果看了我上面 2 篇博客. 还要坚持用 cgo 的. 那.... 你开心就好.
akaHenry
2022-06-13 22:35:22 +08:00
至于 Python 的 FFI + C ABI 非常成熟. (毕竟 Python 性能优化靠 C)

社区实践了几百年了. Python 社区基础库, 基本都是 C 实现.
我是懒得贴了. 没有讨论必要.
Cbdy
2022-06-13 22:50:57 +08:00
jni 确实还行
hhaobao
2022-06-14 01:01:36 +08:00
@orzglory 我觉得你误会了吧, 我只是认真请教, 关于 cgo 我用很久了, 既然你说 cgo 半残是指尽量不要用的意思, 那我就明白了, 我只是以为你能给出一些其它资料能更深入分析的.

看来 V2EX 上还是不能随便请教问题, 只要请教就被当杠精.
hhaobao
2022-06-14 01:06:54 +08:00
@orzglory 另外, 我觉得在描述一样技术时, 把它说成"半残", 这么严重的词, 然后你意思仅是尽量不要用, 我还以为你能补齐它的另一半. 有点意思, 你们都是大牛, 我们都是扛精.

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

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

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

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

© 2021 V2EX