2012-02-16 45 views
19

Đây là một ví dụ đơn giản từ các tài liệu python (http://docs.python.org/extending/extending.html):Cách "chính xác" để chuyển boolean sang phần mở rộng Python C là gì?

static PyObject * 
spam_system(PyObject *self, PyObject *args) 
{ 
    const char *command; 
    int sts; 

    if (!PyArg_ParseTuple(args, "s", &command)) 
     return NULL; 
    sts = system(command); 
    return Py_BuildValue("i", sts); 
} 

Nếu tôi muốn vượt qua một tham số boolean bổ sung cho các chức năng - những gì "đúng" cách để làm điều đó?

Dường như không có tùy chọn bool để chuyển tới PyArg_ParseTuple(). Vì vậy, tôi nghĩ rằng những điều sau đây:

  1. đọc một số nguyên và chỉ sử dụng các giá trị (như bool là một lớp con của int)
  2. gọi PyBool_FromLong() trên một số nguyên
  3. đọc và đối tượng và gọi PyBool_Check () để xác minh nó là một bool
  4. có thể có cách để nhận bất kỳ loại biến nào và nhận giá trị chân lý của nó (tức là một mảng trống sẽ bị hỏng ...) là hàm python thường làm.

Bất kỳ điều nào trong số này thích hợp hơn? Sự lựa chọn khác?

Trả lời

16

4 có thể có cách để nhận bất kỳ loại biến nào và nhận giá trị chân lý của nó (ví dụ: mảng trống sẽ bị hỏng ...) là hàm python thường làm.

Có: (từ Python/C API Reference)

int PyObject_IsTrue(PyObject *o) 

Trả về 1 nếu o đối tượng được coi là đúng, và 0 nếu ngược lại. Điều này tương đương với biểu thức Python không phải là o. Không thành công, trả lại -1.

EDIT. Để trả lời câu hỏi thực tế, tôi nghĩ cách tiếp cận 1 là chính xác, bởi vì int thực sự là loại tương ứng trong C. Phương pháp 4 là tốt, nhưng nếu bạn viết tài liệu của bạn như là một bool, bạn không bắt buộc phải chấp nhận bất kỳ đối tượng nào. Kiểm tra loại rõ ràng như trong 3 mà không có một lý do được tán thành trong Python. Chuyển đổi sang một đối tượng Python khác như trong 2 không giúp mã C của bạn.

13

Hiện tại, phân tích cú pháp một số nguyên (như "i") là cách được chấp nhận để thực hiện một bool.

Từ Python 3.3, PyArg_ParseTuple sẽ chấp nhận "p" (đối với "vị ngữ"), mỗi the latest NEWS:

  • Issue #14705: Các PyArg_Parse() gia đình của các chức năng hiện nay hỗ trợ 'p' định dạng đơn vị, trong đó chấp nhận một đối số "boolean predicate". Nó chuyển đổi bất kỳ giá trị Python thành số nguyên - 0 nếu nó là "false" và 1 nếu không.

Lưu ý rằng khi sử dụng PyArg_ParseTuple với "p", đối số phải là một (con trỏ tới) int, không phải là loại C99 bool:

int x; // not "bool x" 
PyArg_ParseTuple(args, kwds, "p", &x); 
+2

Tôi đã sử dụng điều này và thấy rằng trong C tôi phải khai báo các biến là 'int' (không phải' bool'). Hoặc, khi sử dụng nhiều bool, chúng sẽ không được thiết lập đúng (có thể là một vấn đề với sự khác biệt về kích thước giữa 'bool' và' int'). – szmoore

+0

@szmoore Nó nói rằng nó sử dụng một số nguyên trong phản ứng ở đây. – kevr

+0

Có, nhưng thường trong C bạn có thể sử dụng 'int' và' bool' thay thế cho nhau, trong trường hợp này bạn không thể. Tôi có thể xóa nhận xét của mình nếu nhận xét đó là siêu dữ liệu. – szmoore

6

Tôi đã tìm thấy cách tiếp cận khác:

PyObject* py_expectArgs; 
bool expectArgs; 

PyArg_ParseTupleAndKeywords(args, keywds, (char *)"O!", (char **)kwlist, &PyBool_Type, &py_expectArgs); 

expectArgs = PyObject_IsTrue(py_expectArgs); 

Trong trường hợp cuộc gọi param sai có đối số "tự động" ngoại lệ 1 phải là bool, không phải int "

Các vấn đề liên quan