2012-05-16 14 views
9

Tôi đã cố gắng tìm hiểu cách viết các phần mở rộng C cho Python và muốn chắc chắn rằng tôi hiểu cách PyArg_ParseTupleAndKeywords hoạt động.PyArg_ParseTupleAndKeywords hoạt động như thế nào?

Tôi tin rằng đối số đầu tiên là một con trỏ PyObject trỏ đến một mảng các đối số được chuyển vào hàm C-mở rộng theo thứ tự chúng được truyền đi. Đối số thứ hai là danh sách các từ khóa đã được chuyển, các vị trí mà tại đó chúng được chuyển đi và rất có thể, một số loại cờ chỉ báo cho biết vị trí từ khóa bắt đầu và vị trí trở nên không liên quan.

PyArg_ParseTupleAndKeywords sau đó sử dụng danh sách từ khóa (đối số thứ 4) để ánh xạ giữa các đối số được chỉ định với từ khóa và cả chuỗi định dạng (đối số thứ 3) và địa chỉ của biến C (5th & + arguments). đã sao chép.

Sự hiểu biết của tôi có đúng không? Khi tôi đọc qua tài liệu trực tuyến, tất cả những gì tôi thấy là các tham chiếu đến "đối số vị trí và đối số từ khóa", điều này khiến tôi cảm thấy một chút trong bóng tối. Tệp tin cho trình thông dịch Python xử lý PyArg_ParseTupleAndKeywords ở đâu?

Trả lời

6

Bạn đã đọc qua lời giải thích mở tại http://docs.python.org/c-api/arg.html? Nó làm một công việc khá tốt để giải thích những gì đang xảy ra. Đừng đi ngay đến tham chiếu cụ thể cho PyArg_ParseTupleAndKeywords; nó giả định bạn đọc văn bản ở trên, và không phải là rất hữu ích của chính nó.

Bạn gần như đã nhận được nó. Đối số đầu tiên thực sự là một danh sách các đối số vị trí đến. Thứ hai là bản đồ của các đối số từ khóa đến (ánh xạ tên từ khóa đã cho với giá trị đã cho). Đối số thứ tư thực sự là danh sách các từ khóa mà chức năng của bạn được chuẩn bị để chấp nhận. Có, đối số thứ 3 là chuỗi định dạng và thứ 5 và sau đó là các con trỏ C vào đó các giá trị được sao chép.

Bạn sẽ tìm thấy PyArg_ParseTupleAndKeywords() dưới Python/getargs.c.

+1

Thay vì chỉ C API doc, có là một bản tóm tắt có thể đọc được tốt tại http://docs.python.org/2/extending/extending.html – timbo

2

Để thi đua sau trong python:

def keywords(a, b, foo=None, bar=None, baz=None): 
    pass 

Sau đây sẽ làm việc:

 

static PyObject *keywords(PyObject *self, PyObject *args, PyObject *kwargs) { 
    char *a; 
    char *b; 
    char *foo = NULL; 
    char *bar = NULL; 
    char *baz = NULL; 

    // Note how "a" and "b" are included in this 
    // even though they aren't supposed to be in kwargs like in python 
    static char *kwlist[] = {"a", "b", "foo", "bar", "baz", NULL}; 

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|sss", kwlist, &a, &b, &foo, &bar, &baz)) { 
     return NULL; 
    } 

    printf("a is %s\n", a); 
    printf("b is %s\n", b); 
    printf("foo is %s\n", foo); 
    printf("bar is %s\n", bar); 
    printf("baz is %s\n", baz); 

    Py_RETURN_NONE; 
} 
// ... 
static PyMethodDef SpamMethods[] = { 
    //... 
    {"keywords", (PyCFunction) keywords, METH_VARARGS | METH_KEYWORDS, "practice kwargs"}, 
    {NULL, NULL, 0, NULL} 

Và để sử dụng nó:

 
from spam import keywords 

keywords() // Fails, require a and b 
keywords('a') // fails, requires b 
keywords('a', 'b') 
keywords('a', 'b', foo='foo', bar='bar', baz='baz) 
keywords('a', 'b','foo', 'bar', 'baz') 
keywords(a='a', b='b', foo='foo', bar='bar', baz='baz') 
+0

Lạ - Tôi không thể chỉnh sửa. Khi bạn bỏ chức năng "từ khóa", bạn muốn truyền nó thành 'PyCFunctionWithKeywords', thay vì' PyCFunction'. –