2014-01-21 125 views
4

對不起,如果這太含糊。我最近閱讀了關於python的list.sort()方法,並且讀到它是出於性能原因用C編寫的。編程語言如何調用用其他語言編寫的代碼?

我假設的Python代碼只是傳遞一個列表到C代碼和C代碼通過列表回來了,但如何在Python代碼知道從哪裏傳出來或Ç給它正確的數據類型,以及C代碼如何知道它給出的數據類型?

+3

主要的python實現是用C編寫的,從某種意義上說,這意味着當你運行一個python程序時,你確實運行了一個帶有*非常複雜的配置文件(你的程序)的C程序(解釋器)。因爲C程序是正在運行的程序,所以您的「配置文件」可以與C進行交互。這就是爲什麼JRuby或Jython可以與Java庫或MacRuby與Cocoa交互的原因。 – Linuxios

+0

對於不是python或C特定的替代/通用答案,請參閱:http://stackoverflow.com/questions/4546941/how-do-language-bindings-work/4547427#4547427 – slebetman

回答

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++代碼中的入口點和返回位置。

+0

您是否認爲可以添加一些對於我們這些C恐懼症的人來說,將您的代碼註釋到您的代碼中? – wnnmaw

1

每個計算平臺都有(或應該有)應用程序二進制接口(ABI)。這是一個規範,說明如何在例程之間傳遞參數,如何返回值,機器應處於何種狀態等等。

的ABI將指定的東西,如(例如):

  • 第一個整數參數(最多某些數目的位,說32)將在某個寄存器被傳遞(例如%EAX或R3)。第二個將通過另一個具體的註冊表,等等。
  • 使用寄存器列表後,將在堆棧上傳遞附加的整數參數,從進行調用時堆棧指針值的某個偏移處開始。
  • 指針參數將被視爲與整數參數相同。
  • 浮點參數將在浮點寄存器F1,F2等中傳遞,直到這些寄存器用完爲止,然後在堆棧上。
  • 化合物參數(如結構)將作爲整數參數,如果他們是非常小的(例如,在一個結構4個char對象)或在堆棧上,如果他們是大傳遞。

每個編譯器或其他語言實現將生成符合ABI的代碼,至少在它的例程調用或從其他可能在該語言之外的例程中調用的代碼處。

1

我不能到Python/C相互作用的直接對話,但我可以提供一些背景,這些事情是如何在換屆工作。

在特定的平臺或實現上,有一個指定參數如何傳遞給子例程以及如何將值返回給調用者的指定。針對該平臺或實現的編譯器和解釋器會生成符合該約定的代碼,以便子例程/模塊/用不同語言編寫的任何語言都可以相互通信。

在我的彙編類中,我們有一個任務,我們必須使用VAX彙編器,C和Pascal編寫程序(這是在1980年代中期 白堊紀 1980年代)。司機是在C或Pascal之一(不記得哪一個了),這稱爲程序集例行程序,它調用另一個例程(使用哪種語言寫驅動程序)。我們的彙編代碼必須根據VMS調用約定從堆棧中彈出和推送參數。