我正在探索Python,对Python绑定很感兴趣。请问有人能够解释一下,为什么可以从Python访问C库呢?
有几种方法可以从Python中调用用C编写的代码。
首先,标准库中有一个叫做ctypes的模块。它允许你加载动态链接库(在Windows上是DLL,在Linux上是共享库.so
)并直接从Python中调用这些库中的函数。这些库通常是用C语言编写的。
其次,对于CPython
,有Python/C API。它可以以两种主要方式使用:
一种方式是在C语言中编写动态链接库,以便CPython
将其视为模块(你可以在Python程序中导入它)。Python/C API允许该库定义用C语言编写但仍可从Python中调用的函数。该API非常强大,并提供了操作所有Python数据类型和访问解释器内部的函数。
第二种使用C API的方法是将Python嵌入到用C语言编写的程序中。然后,C程序就能够创建用C语言编写的内置模块并公开C函数,就像使用动态链接库方法一样。该API还允许程序执行脚本,然后导入和使用内置模块。这可以用于创建基于Python的插件系统。
“绑定”通常采用纯Python库使用ctypes
实现,或使用Python/C API作为动态链接库实现。后一种选项有时会与像SWIG这样的工具一起使用,这些工具通过处理生成“样板”代码来简化任务,或者使用Boost.Python,它在Python/C API之上提供了C++ API,使其更容易地与C++代码接口。
更多阅读:外部函数接口
答案很简单,Python (CPython) 解释器是用 C 语言编写的,它可以动态调用其他的 C 库,因此你的 C 扩展模块或嵌入式 C 代码可以在任何其他的 C 代码中轻松调用。
CPython 允许特殊的钩子,以便它可以调用其他的 C 代码或被其他的 C 代码调用。这甚至不需要是 C 语言,任何能够编译成本机代码并具有相同调用约定的语言都可以。
举个简单的例子,假设你创建了一个名为 mython 的程序,它可以加载任何共享库,并尝试调用一个名为 run
的函数。
lib = dlopen("mylib.so", RTLD_LAZY);
func = dlsym(lib, "run");
(*func)();
你已经加载了一个模块并调用了它的代码,CPython 也是这样做的,但是更加复杂,提供更好的接口和对象来传递,此外还涉及内存管理、线程管理等其他细节。
因此,Python 实现的平台必须与它被扩展的语言匹配,例如 CPython 不能在 Java 中进行扩展,但 Python 的 Java 实现称为 Jython 可以在 Java 中进行扩展,类似地,.NET 实现 IronPython 可以在 .Net 语言中进行扩展。