Gọi kịch bản python từ C++

Cho đến nay, chúng tôi đã tập trung vào việc làm cho các hàm C có thể gọi được từ Python. Đảo ngược cũng hữu ích. gọi các hàm Python từ C. Đây là trường hợp đặc biệt đối với các thư viện hỗ trợ cái gọi là hàm ``gọi lại''. Nếu một giao diện C sử dụng các cuộc gọi lại, Python tương đương thường cần cung cấp một cơ chế gọi lại cho lập trình viên Python; . Các công dụng khác cũng có thể tưởng tượng được

May mắn thay, trình thông dịch Python dễ dàng được gọi theo cách đệ quy và có một giao diện chuẩn để gọi một hàm Python. [Tôi sẽ không bàn sâu về cách gọi trình phân tích cú pháp Python với một chuỗi cụ thể làm đầu vào -- nếu bạn quan tâm, hãy xem cách triển khai tùy chọn dòng lệnh "-c" trong "Python/pythonmain. c". ]

Gọi một hàm Python thật dễ dàng. Đầu tiên, chương trình Python bằng cách nào đó phải chuyển cho bạn đối tượng hàm Python. Bạn nên cung cấp một chức năng [hoặc một số giao diện khác] để thực hiện việc này. Khi hàm này được gọi, hãy lưu một con trỏ vào đối tượng hàm Python [hãy cẩn thận với Py_INCREF[] nó. ] trong một biến toàn cục -- hoặc bất cứ nơi nào bạn thấy phù hợp. Ví dụ: chức năng sau đây có thể là một phần của định nghĩa mô-đun

static PyObject *my_callback = NULL;

static PyObject *
my_set_callback[dummy, arg]
    PyObject *dummy, *arg;
{
    Py_XDECREF[my_callback]; /* Dispose of previous callback */
    Py_XINCREF[arg]; /* Add a reference to new callback */
    my_callback = arg; /* Remember new callback */
    /* Boilerplate to return "None" */
    Py_INCREF[Py_None];
    return Py_None;
}

Các macro Py_XINCREF[] và Py_XDECREF[] tăng/giảm số lượng tham chiếu của một đối tượng và an toàn khi có con trỏ NULL. Thông tin thêm về chúng trong phần về Số lượng tham chiếu bên dưới

Sau đó, khi đến lúc gọi hàm, bạn gọi hàm C PyEval_CallObject[]. Hàm này có hai đối số, cả hai đều trỏ tới các đối tượng Python tùy ý. hàm Python và danh sách đối số. Danh sách đối số phải luôn là một đối tượng tuple, có độ dài bằng số lượng đối số. Để gọi hàm Python không có đối số, hãy chuyển một bộ dữ liệu trống; . Py_BuildValue[] trả về một bộ khi chuỗi định dạng của nó bao gồm 0 hoặc nhiều mã định dạng giữa các dấu ngoặc đơn. Ví dụ

    int arg;
    PyObject *arglist;
    PyObject *result;
    ...
    arg = 123;
    ...
    /* Time to call the callback */
    arglist = Py_BuildValue["[i]", arg];
    result = PyEval_CallObject[my_callback, arglist];
    Py_DECREF[arglist];

PyEval_CallObject[] trả về một con trỏ đối tượng Python. đây là giá trị trả về của hàm Python. PyEval_CallObject[] là ``không tính tham chiếu'' đối với các đối số của nó. Trong ví dụ này, một bộ dữ liệu mới đã được tạo để dùng làm danh sách đối số, đó là Py_DECREF[]-ed ngay sau lệnh gọi

Giá trị trả về của PyEval_CallObject[] là ``new''. nó là một đối tượng hoàn toàn mới hoặc nó là một đối tượng hiện có có số lượng tham chiếu đã được tăng lên. Vì vậy, trừ khi bạn muốn lưu nó trong một biến toàn cục, bằng cách nào đó, bạn nên Py_DECREF[] kết quả, thậm chí [đặc biệt là. ] nếu bạn không quan tâm đến giá trị của nó

Tuy nhiên, trước khi bạn làm điều này, điều quan trọng là phải kiểm tra xem giá trị trả về có phải là NULL không. Nếu đúng như vậy, hàm Python sẽ kết thúc bằng cách đưa ra một ngoại lệ. Nếu mã C có tên là PyEval_CallObject[] được gọi từ Python, thì bây giờ mã này sẽ trả về một dấu hiệu lỗi cho trình gọi Python của nó, vì vậy trình thông dịch có thể in dấu vết ngăn xếp hoặc mã Python đang gọi có thể xử lý ngoại lệ. Nếu điều này là không thể hoặc không mong muốn, ngoại lệ sẽ được xóa bằng cách gọi PyErr_Clear[]. Ví dụ

    if [result == NULL]
        return NULL; /* Pass error back */
    ...use result...
    Py_DECREF[result];

Tùy thuộc vào giao diện mong muốn của hàm gọi lại Python, bạn cũng có thể phải cung cấp danh sách đối số cho PyEval_CallObject[]. Trong một số trường hợp, danh sách đối số cũng được cung cấp bởi chương trình Python, thông qua cùng một giao diện đã chỉ định chức năng gọi lại. Sau đó, nó có thể được lưu và sử dụng theo cách tương tự như đối tượng chức năng. Trong các trường hợp khác, bạn có thể phải xây dựng một bộ dữ liệu mới để chuyển làm danh sách đối số. Cách đơn giản nhất để làm điều này là gọi Py_BuildValue[]. Ví dụ: nếu bạn muốn chuyển mã sự kiện tích hợp, bạn có thể sử dụng mã sau

    PyObject *arglist;
    ...
    arglist = Py_BuildValue["[l]", eventcode];
    result = PyEval_CallObject[my_callback, arglist];
    Py_DECREF[arglist];
    if [result == NULL]
        return NULL; /* Pass error back */
    /* Here maybe use the result */
    Py_DECREF[result];

Lưu ý vị trí của "Py_DECREF[arglist]" ngay sau cuộc gọi, trước khi kiểm tra lỗi. Cũng lưu ý rằng nói một cách chính xác thì mã này chưa hoàn thành. Py_BuildValue[] có thể hết bộ nhớ và điều này cần được kiểm tra

Làm cách nào để gọi tập lệnh Python từ C?

Vì vậy, chúng ta sẽ sử dụng quy tắc sau để gọi hàm Python. .
Khởi tạo môi trường Python
Nhập mô-đun Python
Lấy tham chiếu đến hàm Python, để gọi
Kiểm tra xem chức năng có thể được gọi hay không và gọi nó
Sau đó phản đối đối tượng Python được trả về, được trả về bởi hàm, sau khi thực thi

Chúng ta có thể gọi mã Python từ C không?

Biên dịch Python sang C . Các mô-đun C đó có thể là thư viện C chung hoặc thư viện được xây dựng riêng để hoạt động với Python. Python code can make calls directly into C modules. Those C modules can be either generic C libraries or libraries built specifically to work with Python.

Python có thể tương tác với C không?

Nói chung, mã C đã được viết sẵn sẽ không yêu cầu sửa đổi để Python sử dụng . Công việc duy nhất chúng ta cần làm để tích hợp mã C trong Python là ở phía Python. Các bước giao tiếp Python với C bằng Ctypes.

Tôi có thể gọi tập lệnh Python từ tập lệnh khác không?

Dòng đầu tiên của 'nhập python_2' trong tập lệnh python_1, sẽ gọi tập lệnh python_2 thứ hai. Bất cứ khi nào bạn muốn chạy một tập lệnh Python từ một tập lệnh khác, bạn sẽ cần nhập tên chính xác của tập lệnh Python mà bạn muốn gọi .

Chủ Đề