编程语言如何调用用另一种语言编写的代码?

时间:2014-01-21 14:52:21

标签: python c language-agnostic cpython

很抱歉,如果这太模糊了。我最近在阅读有关python的list.sort()方法的内容,并且因为性能原因读到它是用C语言编写的。

我假设python代码只是将列表传递给C代码并且C代码传回一个列表,但是python代码如何知道传递它的位置或者C给它正确的数据类型,以及C代码如何知道它给出的数据类型?

3 个答案:

答案 0 :(得分:6)

Python可以用C / C ++进行扩展(更多信息here

它基本上意味着您可以像这样包装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 ++代码中的入口点和返回位置。

答案 1 :(得分:1)

每个计算平台都有(或应该有)应用程序二进制接口(ABI)。这是如何在例程之间传递参数,返回值的方式,机器应处于什么状态等的规范。

ABI将指定诸如(例如):

之类的内容
  • 第一个整数参数(最多一些位,比如32)将在某个寄存器(例如%EAX或R3)中传递。第二个将在另一个特定的寄存器中传递,等等。
  • 在使用寄存器列表之后,将在堆栈上传递其他整数参数,从调用时的堆栈指针值起一定偏移量开始。
  • 指针参数将被视为与整数参数相同。
  • 浮点参数将在浮点寄存器F1,F2等中传递,直到这些寄存器用完为止,然后再堆栈。
  • 复合参数(例如结构)如果它们非常小(例如,一个结构中有四个char个对象),则会作为整数参数传递,如果它们很大,则会在堆栈中传递。

每个编译器或其他语言实现都将生成符合ABI的代码,至少在其例程调用或从其他可能在语言之外的例程调用的情况下。

答案 2 :(得分:1)

我不能直接谈论Python / C交互,但我可以提供一些背景知道这些事情是如何工作的。

在特定平台或实现上,有一个 calling convention ,它指定如何将参数传递给子例程以及如何将值返回给调用者。针对该平台或实现的编译器和解释器生成符合该约定的代码,因此子例程/模块/用不同语言编写的任何内容都可以相互通信。

在我的汇编类中,我们有一个赋值,我们必须使用VAX汇编程序,C和Pascal编写程序(这是在白垩纪 1980年代)。驱动程序位于C或Pascal之一(不记得哪一个),它调用了程序集例程,它调用了另一个例程(用驱动程序没有的任何语言编写)。我们的汇编代码必须根据VMS调用约定从堆栈中弹出和推送参数。