跨语言之间的调用,原理是什么?

2020-12-01 16:10:07 +08:00
 James369
比如:
java 通过 jni 调用 c/c++模块。
python 通过 pybind11 调用 c/c++模块。

这是一种基于编译器 /解释器的技术,还是什么二进制原理?
7028 次点击
所在节点    程序员
26 条回复
pursuer
2020-12-01 16:19:18 +08:00
按照对应平台的 abi 调用规则去调就可以了,有些比如 lua 的 c 接口倒是平台无关的
janus77
2020-12-01 16:27:07 +08:00
建议百度 jni 原理
xx6412223
2020-12-01 16:27:13 +08:00
对 Java 来说和 c 一样,就是动态加载链接库的过程,面试的时候基本能答出来 dlopen dlsym 就给过了
TargaryenChen
2020-12-01 16:40:54 +08:00
最近正好在做一个 JSI 相关的内容,JSI 是啥? 可以看下我写的这篇文章 https://www.hellohub.cn/react-native/
简单来说就是在 js 引擎( v8 )和 native ( c++)之间的一个封装层。
比方说 react-native 中就有 jsi,他做的事情就是在 native 侧向 js 中注入方法,然后在 js 侧调用注入的方法并进行传参,这就实现了 js -> c++的通讯。 同理可以利用 v8 提供的方法调用你在 js 侧 global 上注册的方法并传参,这就实现了 c++ -> js 的通讯。至于传递参数的数据类型在两侧一定是有差异的,v8 提供相应的数据类型比方说 v8::String 能够将 c++侧的 std::string 和 js 侧的 string 类型相互转换。
James369
2020-12-01 16:42:09 +08:00
@janus77 百度就没意思了,一起讨论才能活跃论坛,还可以撞出火花。
zunceng
2020-12-01 16:43:32 +08:00
当然是协议啊 从 ffi 到 rpc 约定好了大家都认的协议 不就能互相调用了么
James369
2020-12-01 17:07:54 +08:00
@zunceng 没那么简单吧,应该分编译型语言 A 和解释型语言 B,那么有四种情况:
A call B, B call A, A call A, B call B
liusir
2020-12-01 17:08:32 +08:00
大神们讨论,我来学习一下
icexin
2020-12-01 17:55:32 +08:00
拿 Python 举例吧,用一种易于理解的方式简单说一下。

假设你想让 Python 能调用 c 标准库里面的 puts 来打印字符串,首先需要使用 c 语言编写一个 so 模块,这个模块里面有一个签名类似 PyObject* py_puts(PyObject *self, PyObject *args)这样的 c 函数。
在这个函数内部使用 python 源代码提供的工具函数解析 args,从而获取 python 传递过来的字符串参数,转换成 c 的字符串类型 char*,再传递给 puts 来打印。然后在 python 约定的模块初始化函数里面把 py_puts 注册到 python runtime 里面,一旦这个模块被加载,之后在 python 代码里面就可以调用 py_puts 来打印字符串了。

那你可能问 py_puts 这个 c 函数又是怎么被调用的?原理很简单,因为 cpython 的解释器是用 c 写的,当用户在脚本里面调用 py_puts 的时候,解释器通过查表得到了我们之前注册到 runtime 的函数指针,之后就是 c 函数调用 c 函数了。
Seawalker
2020-12-01 18:03:19 +08:00
同一进城下,都是操作内存中的指针来实现
zunceng
2020-12-01 19:06:13 +08:00
@James369 你想的太复杂了 n 种语言 调用的放式复杂度就是 n^2 了
实际操作大部分语言都是以 so 格式或者 在其基础上约定一种格式( jni )来调用 c 语言,能调用 c 语言后其他语言调用就简单多了, 那么前面提到的方式 就是一种协议 /约定。

参考资料 https://en.wikipedia.org/wiki/Foreign_function_interface
zunceng
2020-12-01 19:13:59 +08:00
@James369 更好理解 /更实用一些的跨语言调用, 用 rpc ( grpc/thirft/jsonrpc/...)来实现跨语言调用, 一组服务通过网络调用约定好的各自提供的接口。这也是一种协议 /约定
kingfalse
2020-12-01 19:20:28 +08:00
还记得第一次搞 jna 是为了 winring0 模拟按键去登录网银控,件做爬,虫,想想就后怕
hhhsuan
2020-12-01 19:22:56 +08:00
java 和 python 解释器不都是用 C 写的吗? C 调用 C 有啥问题?
DoctorCat
2020-12-01 19:27:43 +08:00
动态链接库具备了语言无关的这种特性。本质上是 OS 提供的机制。
billlee
2020-12-01 21:35:06 +08:00
实际上就是大家都按 C 的接口来调用
nightwitch
2020-12-01 23:05:57 +08:00
不同语言之间形成一些约定啊,最常见的就是约定为 C 的 ABI 。因为操作系统的 API 和库往往以 C 的 API/ABI 提供,所以一个编程语言要使用操作系统提供的功能就要实现与 C 语言的库的交互。
Yourshell
2020-12-01 23:07:22 +08:00
按照约定读写内存,猜的。
icyalala
2020-12-01 23:16:09 +08:00
去 Google 搜 calling convention
不同 CPU 架构不一样( x86 、x64 、arm ),不同语言不一样,即使同语言也有多种声明,比如 x86 的 stdcall, fastcall, cdecl.
Jirajine
2020-12-01 23:21:53 +08:00
调用就是 把数据传给另一个语言写的程序->执行该程序得到结果->取回该结果。
无论是通过 abi 、rpc 还是 rest,本质上都是一回事。

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

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

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

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

© 2021 V2EX