Question

Sorry if this is too vague. I was recently reading about python's list.sort() method and read that it was written in C for performance reasons.

I'm assuming that the python code just passes a list to the C code and the C code passes a list back, but how does the python code know where to pass it or that C gave it the correct data type, and how does the C code know what data type it was given?

Was it helpful?

Solution

Python can be extended in C/C++ (more info here)

It basically means that you can wrap a C module like this

#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 */
};

And using the Python header files it will define and understand entry points and return locations in the C/C++ code.

OTHER TIPS

I can't speak to Python/C interaction directly, but I can give some background to how these sorts of things work in general.

On a particular platform or implementation, there is a calling convention that specifies how parameters are passed to subroutines and how values are returned to the caller. Compilers and interpreters that target that platform or implementation generate code to conform to that convention, so that subroutines/modules/whatever written in different languages can communicate with each other.

In my assembly class, we had an assignment where we had to write a program using VAX assembler, C, and Pascal (this was in the mid-Cretaceous1980s). The driver was in one of C or Pascal (can't remember which anymore), which called the assembly routine, which called the other routine (which was written in whichever language the driver wasn't). Our assembly code had to pop and push parameters from the stack based on the VMS calling convention.

Each computing platform has (or should have) an application binary interface (ABI). This is a specification of how parameters are passed between routines, how values are returned, what state the machine should be in and so on.

The ABI will specify things such as (for example):

  • The first integer argument (up to some number of bits, say 32) will be passed in a certain register (such as %EAX or R3). The second will be passed in another specific, register, and so on.
  • After the list of register is used, additional integer arguments will be passed on the stack, starting at a certain offset from the value of the stack pointer when the call is made.
  • Pointer arguments will be treated the same as integer arguments.
  • Floating-point arguments will be passed in floating-point registers F1, F2, and so on, until those registers are used up, and then on the stack.
  • Compound arguments (such as structures) will be passed as integer arguments if they are very small (e.g., four char objects in one structure) or on the stack if they are large.

Each compiler or other language implementation will generate code that conforms to the ABI, at least where its routines call or are called from other routines that might be outside the language.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top