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 函数了。