抱歉,如果这太模糊了。我最近读到了python的list.sort()方法,读到它是出于性能原因用C编写的。
我假设 python 代码只是将列表传递给 C 代码,而 C 代码将列表传递回去,但是 python 代码如何知道在哪里传递它或 C 给了它正确的数据类型,C 代码如何知道它被赋予了什么数据类型?
Python 可以在 C/C++ 中扩展(更多信息在这里)
这基本上意味着你可以像这样包装一个 C 模块
#include "Python.h"
// Static function returning a PyObject pointer
static PyObject *
keywdarg_parrot(PyObject *self, PyObject *args, PyObject *keywds)
// takes self, args and kwargs.
{
int voltage;
// No such thing as strings here. Its a tough life.
char *state = "a stiff";
char *action = "voom";
char *type = "Norwegian Blue";
// Possible keywords
static char *kwlist[] = {"voltage", "state", "action", "type", NULL};
// unpack arguments
if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|sss", kwlist,
&voltage, &state, &action, &type))
return NULL;
// print to stdout
printf("-- This parrot wouldn't %s if you put %i Volts through it.n",
action, voltage);
printf("-- Lovely plumage, the %s -- It's %s!n", type, state);
// Reference count some None.
Py_INCREF(Py_None);
// return some none.
return Py_None;
}
// Static PyMethodDef
static PyMethodDef keywdarg_methods[] = {
/* The cast of the function is necessary since PyCFunction values
* only take two PyObject* parameters, and keywdarg_parrot() takes
* three.
*/
// Declare the parrot function, say what it takes and give it a doc string.
{"parrot", (PyCFunction)keywdarg_parrot, METH_VARARGS | METH_KEYWORDS,
"Print a lovely skit to standard output."},
{NULL, NULL, 0, NULL} /* sentinel */
};
使用 Python 头文件,它将定义和理解 C/C++ 代码中的入口点和返回位置。
我不能直接谈论 Python/C 交互,但我可以给出一些关于这些事情如何工作的背景。
在特定平台或实现上,有一个调用约定,用于指定如何将参数传递给子例程以及如何将值返回给调用方。面向该平台或实现的编译器和解释器生成符合该约定的代码,以便子例程/模块/用不同语言编写的任何内容都可以相互通信。
在我的汇编课上,我们有一个作业,我们必须使用 VAX 汇编器、C 和 Pascal 编写一个程序(这是在 1980 年代中期)。驱动程序是 C 或 Pascal 中的一个(不记得了,它调用了汇编例程,它调用了另一个例程(它是用驱动程序不是哪种语言编写的)。 我们的汇编代码必须根据 VMS 调用约定从堆栈中弹出和推送参数。
每个计算平台都有(或应该有)一个应用程序二进制接口(ABI)。这是关于如何在例程之间传递参数、如何返回值、计算机应处于什么状态等的规范。
ABI 将指定诸如以下内容(例如):
- 第一个整数参数(最多一定数量的位,例如 32)将在某个寄存器(例如 %EAX 或 R3)中传递。第二个将在另一个特定的寄存器中传递,依此类推。
- 使用寄存器列表后,将在堆栈上传递其他整数参数,从调用时堆栈指针值的某个偏移量开始。
- 指针参数将被视为与整数参数相同。 浮
- 点参数将在浮点寄存器 F1、F2 等中传递,直到这些寄存器用完,然后在堆栈上传递。 复合参数(例如结构
- )将作为整数参数传递,如果它们非常小(例如,一个结构中有四个
char
对象),或者如果它们很大,则在堆栈上传递。
每个编译器或其他语言实现都将生成符合 ABI 的代码,至少在其例程调用或从可能位于语言之外的其他例程调用的代码中
。