Python có thể được biên dịch thành c

Có một số cách để bạn có thể mở rộng chức năng của Python. Một trong số đó là viết mô-đun Python của bạn bằng C hoặc C++. Quá trình này có thể dẫn đến hiệu suất được cải thiện và khả năng truy cập tốt hơn vào các chức năng của thư viện C và các cuộc gọi hệ thống. Trong hướng dẫn này, bạn sẽ khám phá cách sử dụng API Python để viết các mô-đun mở rộng Python C

Bạn sẽ học cách

  • Gọi các hàm C từ bên trong Python
  • Truyền đối số từ Python sang C và phân tích chúng cho phù hợp
  • Tăng ngoại lệ từ mã C và tạo ngoại lệ Python tùy chỉnh trong C
  • Xác định các hằng số toàn cầu trong C và làm cho chúng có thể truy cập được bằng Python
  • Kiểm tra, đóng gói và phân phối mô-đun mở rộng Python C của bạn

Tải xuống miễn phí. Nhận một chương mẫu từ Thủ thuật Python. Cuốn sách chỉ cho bạn các phương pháp hay nhất về Python với các ví dụ đơn giản mà bạn có thể áp dụng ngay lập tức để viết mã Pythonic + đẹp hơn

Mở rộng chương trình Python của bạn

Một trong những tính năng ít được biết đến nhưng vô cùng mạnh mẽ của Python là khả năng gọi các hàm và thư viện được xác định bằng các ngôn ngữ được biên dịch như C hoặc C++. Điều này cho phép bạn mở rộng các khả năng của chương trình ngoài những gì mà các tính năng tích hợp sẵn của Python cung cấp

Có nhiều ngôn ngữ bạn có thể chọn để mở rộng chức năng của Python. Vì vậy, tại sao bạn nên sử dụng C?

  1. Để triển khai các loại đối tượng tích hợp mới. Có thể viết một lớp Python bằng C, sau đó khởi tạo và mở rộng lớp đó từ chính Python. Có thể có nhiều lý do để làm điều này, nhưng thường xuyên hơn không, hiệu suất chủ yếu là thứ thúc đẩy các nhà phát triển chuyển sang C. Trường hợp như vậy rất hiếm, nhưng thật tốt khi biết mức độ mà Python có thể được mở rộng

  2. Để gọi các chức năng thư viện C và các cuộc gọi hệ thống. Nhiều ngôn ngữ lập trình cung cấp giao diện cho các cuộc gọi hệ thống được sử dụng phổ biến nhất. Tuy nhiên, có thể có các cuộc gọi hệ thống ít được sử dụng khác chỉ có thể truy cập thông qua C. Mô-đun

     1#include 
     2
     3static PyObject *method_fputs[PyObject *self, PyObject *args] {
     4    char *str, *filename = NULL;
     5    int bytes_copied = -1;
     6
     7    /* Parse arguments */
     8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     9        return NULL;
    10    }
    11
    12    FILE *fp = fopen[filename, "w"];
    13    bytes_copied = fputs[str, fp];
    14    fclose[fp];
    15
    16    return PyLong_FromLong[bytes_copied];
    17}
    
    5 trong Python là một ví dụ

Đây không phải là một danh sách đầy đủ, nhưng nó cung cấp cho bạn ý chính về những gì có thể được thực hiện khi mở rộng Python bằng C hoặc bất kỳ ngôn ngữ nào khác

Để viết các mô-đun Python bằng C, bạn sẽ cần sử dụng API Python, API này xác định các hàm, macro và biến khác nhau cho phép trình thông dịch Python gọi mã C của bạn. Tất cả những công cụ này và nhiều công cụ khác được gói chung trong

Loại bỏ các quảng cáo

Viết giao diện Python trong C

Trong hướng dẫn này, bạn sẽ viết một trình bao bọc nhỏ cho hàm thư viện C, sau đó bạn sẽ gọi hàm này từ bên trong Python. Việc tự triển khai trình bao bọc sẽ cho bạn ý tưởng tốt hơn về thời điểm và cách sử dụng C để mở rộng mô-đun Python của bạn

Thấu hiểu
 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7 là chức năng thư viện C mà bạn sẽ thực hiện

int fputs[const char *, FILE *]

Hàm này nhận hai đối số

  1.  1#include 
     2
     3static PyObject *method_fputs[PyObject *self, PyObject *args] {
     4    char *str, *filename = NULL;
     5    int bytes_copied = -1;
     6
     7    /* Parse arguments */
     8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     9        return NULL;
    10    }
    11
    12    FILE *fp = fopen[filename, "w"];
    13    bytes_copied = fputs[str, fp];
    14    fclose[fp];
    15
    16    return PyLong_FromLong[bytes_copied];
    17}
    
    9 là một mảng ký tự
  2.  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Snip */
    
    0 là con trỏ luồng tệp

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7 ghi mảng ký tự vào tệp được chỉ định bởi luồng tệp và trả về giá trị không âm. Nếu thao tác thành công, thì giá trị này sẽ biểu thị số byte được ghi vào tệp. Nếu có lỗi, nó sẽ trả về
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */
2. Bạn có thể đọc thêm về chức năng thư viện C này và các biến thể khác của nó trong mục nhập trang thủ công

Viết Hàm C cho
 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7

Đây là một chương trình C cơ bản sử dụng

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7 để ghi một chuỗi vào luồng tệp

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}

Đoạn mã này có thể được tóm tắt như sau

  1. Mở tệp
     1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Snip */
    
    5
  2. Viết chuỗi
     1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Snip */
    
    6 vào tệp

Ghi chú. Mã C trong bài viết này nên được xây dựng trên hầu hết các hệ thống. Nó đã được thử nghiệm trên GCC mà không sử dụng bất kỳ cờ đặc biệt nào

Trong phần sau, bạn sẽ viết một hàm bao cho hàm C này

Bao bì
 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7

Có vẻ hơi lạ khi xem mã đầy đủ trước khi giải thích về cách thức hoạt động của nó. Tuy nhiên, dành một chút thời gian để kiểm tra sản phẩm cuối cùng sẽ bổ sung cho sự hiểu biết của bạn trong các phần sau. Khối mã bên dưới hiển thị phiên bản được gói cuối cùng của mã C của bạn

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}

Đoạn mã này tham chiếu ba cấu trúc đối tượng được định nghĩa trong

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
6

  1.  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Snip */
    
    9
  2.  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Parse arguments */
     6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     7        return NULL;
     8    }
     9
    10    /* Snip */
    
    0
  3.  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Parse arguments */
     6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     7        return NULL;
     8    }
     9
    10    /* Snip */
    
    1

Chúng được sử dụng để định nghĩa kiểu dữ liệu cho ngôn ngữ Python. Bạn sẽ đi qua từng người trong số họ bây giờ

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */
9

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */
9 là một cấu trúc đối tượng mà bạn sử dụng để xác định các loại đối tượng cho Python. Tất cả các đối tượng Python chia sẻ một số lượng nhỏ các trường được xác định bằng cấu trúc
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */
9. Tất cả các loại đối tượng khác là phần mở rộng của loại này

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */
9 yêu cầu trình thông dịch Python coi một con trỏ tới một đối tượng là một đối tượng. Chẳng hạn, đặt kiểu trả về của hàm trên là
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */
9 xác định các trường phổ biến mà trình thông dịch Python yêu cầu để nhận dạng đây là kiểu Python hợp lệ

Hãy xem lại một vài dòng đầu tiên của mã C của bạn

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */

Ở dòng 2, bạn khai báo các loại đối số mà bạn muốn nhận từ mã Python của mình

  1.  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Parse arguments */
     6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     7        return NULL;
     8    }
     9
    10    /* Snip */
    
    7 là chuỗi bạn muốn ghi vào luồng tệp
  2.  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Parse arguments */
     6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     7        return NULL;
     8    }
     9
    10    /* Snip */
    
    8 là tên của tệp để ghi vào

PyArg_ParseTuple[]

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    /* Snip */
0 phân tích các đối số bạn sẽ nhận được từ chương trình Python của mình thành các biến cục bộ

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    /* Snip */

Nếu bạn nhìn vào dòng 6, thì bạn sẽ thấy rằng

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    /* Snip */
0 nhận các đối số sau

  •  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Parse arguments */
     6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     7        return NULL;
     8    }
     9
    10    FILE *fp = fopen[filename, "w"];
    11    bytes_copied = fputs[str, fp];
    12    fclose[fp];
    13
    14    return PyLong_FromLong[bytes_copied];
    15}
    
    1 thuộc loại
     1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Snip */
    
    9

  •  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Parse arguments */
     6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     7        return NULL;
     8    }
     9
    10    FILE *fp = fopen[filename, "w"];
    11    bytes_copied = fputs[str, fp];
    12    fclose[fp];
    13
    14    return PyLong_FromLong[bytes_copied];
    15}
    
    3 là trình xác định định dạng chỉ định loại dữ liệu của các đối số để phân tích cú pháp. [Bạn có thể xem tài liệu chính thức để tham khảo đầy đủ. ]

  •  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Parse arguments */
     6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     7        return NULL;
     8    }
     9
    10    FILE *fp = fopen[filename, "w"];
    11    bytes_copied = fputs[str, fp];
    12    fclose[fp];
    13
    14    return PyLong_FromLong[bytes_copied];
    15}
    
    4 và
     1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Parse arguments */
     6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     7        return NULL;
     8    }
     9
    10    FILE *fp = fopen[filename, "w"];
    11    bytes_copied = fputs[str, fp];
    12    fclose[fp];
    13
    14    return PyLong_FromLong[bytes_copied];
    15}
    
    5 là các con trỏ tới các biến cục bộ mà các giá trị được phân tích cú pháp sẽ được gán

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    /* Snip */
0 đánh giá thành
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    FILE *fp = fopen[filename, "w"];
11    bytes_copied = fputs[str, fp];
12    fclose[fp];
13
14    return PyLong_FromLong[bytes_copied];
15}
7 khi thất bại. Nếu không thành công thì hàm sẽ trả về
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    FILE *fp = fopen[filename, "w"];
11    bytes_copied = fputs[str, fp];
12    fclose[fp];
13
14    return PyLong_FromLong[bytes_copied];
15}
8 và không tiếp tục nữa

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7

Như bạn đã thấy trước đây,

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7 có hai đối số, một trong số đó là đối tượng
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */
0. Vì bạn không thể phân tích cú pháp một đối tượng
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    FILE *fp = fopen[filename, "w"];
11    bytes_copied = fputs[str, fp];
12    fclose[fp];
13
14    return PyLong_FromLong[bytes_copied];
15}
2 Python bằng API Python trong C, nên bạn sẽ phải sử dụng một giải pháp thay thế

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    FILE *fp = fopen[filename, "w"];
11    bytes_copied = fputs[str, fp];
12    fclose[fp];
13
14    return PyLong_FromLong[bytes_copied];
15}

Đây là một sự cố về những gì mã này làm

  • Ở dòng 10, bạn đang chuyển tên của tệp mà bạn sẽ sử dụng để tạo một đối tượng
     1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Snip */
    
    0 và chuyển nó cho hàm
  • Ở dòng 11, bạn gọi
     1#include 
     2
     3static PyObject *method_fputs[PyObject *self, PyObject *args] {
     4    char *str, *filename = NULL;
     5    int bytes_copied = -1;
     6
     7    /* Parse arguments */
     8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     9        return NULL;
    10    }
    11
    12    FILE *fp = fopen[filename, "w"];
    13    bytes_copied = fputs[str, fp];
    14    fclose[fp];
    15
    16    return PyLong_FromLong[bytes_copied];
    17}
    
    7 với các đối số sau
    •  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
       2    char *str, *filename = NULL;
       3    int bytes_copied = -1;
       4
       5    /* Parse arguments */
       6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
       7        return NULL;
       8    }
       9
      10    FILE *fp = fopen[filename, "w"];
      11    bytes_copied = fputs[str, fp];
      12    fclose[fp];
      13
      14    return PyLong_FromLong[bytes_copied];
      15}
      
      5 là chuỗi bạn muốn ghi vào tệp
    •  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
       2    char *str, *filename = NULL;
       3    int bytes_copied = -1;
       4
       5    /* Parse arguments */
       6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
       7        return NULL;
       8    }
       9
      10    FILE *fp = fopen[filename, "w"];
      11    bytes_copied = fputs[str, fp];
      12    fclose[fp];
      13
      14    return PyLong_FromLong[bytes_copied];
      15}
      
      6 là đối tượng
       1static PyObject *method_fputs[PyObject *self, PyObject *args] {
       2    char *str, *filename = NULL;
       3    int bytes_copied = -1;
       4
       5    /* Snip */
      
      0 bạn đã xác định ở dòng 10

Sau đó, bạn lưu trữ giá trị trả về của

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7 trong
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    FILE *fp = fopen[filename, "w"];
11    bytes_copied = fputs[str, fp];
12    fclose[fp];
13
14    return PyLong_FromLong[bytes_copied];
15}
9. Biến số nguyên này sẽ được trả về lệnh gọi
 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7 trong trình thông dịch Python

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
1

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    /* Snip */
1 trả về một
static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
3, đại diện cho một đối tượng số nguyên trong Python. Bạn có thể tìm thấy nó ở cuối mã C của mình

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    FILE *fp = fopen[filename, "w"];
11    bytes_copied = fputs[str, fp];
12    fclose[fp];
13
14    return PyLong_FromLong[bytes_copied];
15}

Dòng 14 tạo một

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
3 cho
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    FILE *fp = fopen[filename, "w"];
11    bytes_copied = fputs[str, fp];
12    fclose[fp];
13
14    return PyLong_FromLong[bytes_copied];
15}
9, biến được trả về khi hàm được gọi trong Python. Bạn phải trả lại một
static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
6 từ mô-đun mở rộng Python C của bạn cho trình thông dịch Python

Loại bỏ các quảng cáo

Viết hàm init

Bạn đã viết mã tạo nên chức năng cốt lõi của mô-đun mở rộng Python C của mình. Tuy nhiên, vẫn còn một vài chức năng bổ sung cần thiết để khởi động và chạy mô-đun của bạn. Bạn sẽ cần viết các định nghĩa về mô-đun của mình và các phương thức chứa trong đó, như vậy

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};

Các chức năng này bao gồm thông tin meta về mô-đun của bạn sẽ được trình thông dịch Python sử dụng. Hãy đi qua từng cấu trúc ở trên để xem cách chúng hoạt động

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
7

Để gọi các phương thức được xác định trong mô-đun của bạn, trước tiên bạn cần thông báo cho trình thông dịch Python về chúng. Để làm điều này, bạn có thể sử dụng

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
7. Đây là cấu trúc có 4 thành viên đại diện cho một phương thức duy nhất trong mô-đun của bạn

Lý tưởng nhất là sẽ có nhiều hơn một phương thức trong mô-đun mở rộng Python C của bạn mà bạn muốn có thể gọi được từ trình thông dịch Python. Đây là lý do tại sao bạn cần xác định một mảng gồm

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
7 cấu trúc

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};

Mỗi thành viên riêng lẻ của cấu trúc chứa thông tin sau

  • static PyMethodDef FputsMethods[] = {
        {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
        {NULL, NULL, 0, NULL}
    };
    
    0 là tên người dùng sẽ viết để gọi chức năng cụ thể này

  • static PyMethodDef FputsMethods[] = {
        {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
        {NULL, NULL, 0, NULL}
    };
    
    1 là tên của hàm C cần gọi

  • static PyMethodDef FputsMethods[] = {
        {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
        {NULL, NULL, 0, NULL}
    };
    
    2 là cờ báo cho trình thông dịch biết rằng hàm sẽ chấp nhận hai đối số kiểu
    static PyMethodDef FputsMethods[] = {
        {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
        {NULL, NULL, 0, NULL}
    };
    
    
    static struct PyModuleDef fputsmodule = {
        PyModuleDef_HEAD_INIT,
        "fputs",
        "Python interface for the fputs C library function",
        -1,
        FputsMethods
    };
    
    6

    1. static PyMethodDef FputsMethods[] = {
          {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
          {NULL, NULL, 0, NULL}
      };
      
      4 là đối tượng mô-đun
    2.  1static PyObject *method_fputs[PyObject *self, PyObject *args] {
       2    char *str, *filename = NULL;
       3    int bytes_copied = -1;
       4
       5    /* Parse arguments */
       6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
       7        return NULL;
       8    }
       9
      10    FILE *fp = fopen[filename, "w"];
      11    bytes_copied = fputs[str, fp];
      12    fclose[fp];
      13
      14    return PyLong_FromLong[bytes_copied];
      15}
      
      1 là một bộ chứa các đối số thực sự cho chức năng của bạn. Như đã giải thích trước đây, các đối số này được giải nén bằng cách sử dụng
       1static PyObject *method_fputs[PyObject *self, PyObject *args] {
       2    char *str, *filename = NULL;
       3    int bytes_copied = -1;
       4
       5    /* Parse arguments */
       6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
       7        return NULL;
       8    }
       9
      10    /* Snip */
      
      0

  • Chuỗi cuối cùng là một giá trị để đại diện cho phương thức

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};
7

Giống như

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
7 chứa thông tin về các phương thức trong mô-đun mở rộng Python C của bạn, cấu trúc
static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};
7 chứa thông tin về chính mô-đun của bạn. Nó không phải là một mảng các cấu trúc, mà là một cấu trúc duy nhất được sử dụng để định nghĩa mô-đun

static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};

Có tổng cộng 9 thành viên trong cấu trúc này, nhưng không phải tất cả chúng đều bắt buộc. Trong khối mã ở trên, bạn khởi tạo năm mã sau

  1. static struct PyModuleDef fputsmodule = {
        PyModuleDef_HEAD_INIT,
        "fputs",
        "Python interface for the fputs C library function",
        -1,
        FputsMethods
    };
    
    0 là thành viên của loại
    static struct PyModuleDef fputsmodule = {
        PyModuleDef_HEAD_INIT,
        "fputs",
        "Python interface for the fputs C library function",
        -1,
        FputsMethods
    };
    
    1, nên chỉ có một giá trị này

  2. static PyMethodDef FputsMethods[] = {
        {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
        {NULL, NULL, 0, NULL}
    };
    
    0 là tên của mô-đun mở rộng Python C của bạn

  3. Chuỗi là giá trị đại diện cho chuỗi tài liệu mô-đun của bạn. Bạn có thể sử dụng

     1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Parse arguments */
     6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     7        return NULL;
     8    }
     9
    10    FILE *fp = fopen[filename, "w"];
    11    bytes_copied = fputs[str, fp];
    12    fclose[fp];
    13
    14    return PyLong_FromLong[bytes_copied];
    15}
    
    8 để không có chuỗi tài liệu hoặc bạn có thể chỉ định một chuỗi tài liệu bằng cách chuyển một số
     1#include 
     2
     3static PyObject *method_fputs[PyObject *self, PyObject *args] {
     4    char *str, *filename = NULL;
     5    int bytes_copied = -1;
     6
     7    /* Parse arguments */
     8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     9        return NULL;
    10    }
    11
    12    FILE *fp = fopen[filename, "w"];
    13    bytes_copied = fputs[str, fp];
    14    fclose[fp];
    15
    16    return PyLong_FromLong[bytes_copied];
    17}
    
    9 như được hiển thị trong đoạn mã trên. Nó thuộc loại
    static struct PyModuleDef fputsmodule = {
        PyModuleDef_HEAD_INIT,
        "fputs",
        "Python interface for the fputs C library function",
        -1,
        FputsMethods
    };
    
    5. Bạn cũng có thể sử dụng
    static struct PyModuleDef fputsmodule = {
        PyModuleDef_HEAD_INIT,
        "fputs",
        "Python interface for the fputs C library function",
        -1,
        FputsMethods
    };
    
    6 để xác định chuỗi tài liệu cho mô-đun của mình

  4. static struct PyModuleDef fputsmodule = {
        PyModuleDef_HEAD_INIT,
        "fputs",
        "Python interface for the fputs C library function",
        -1,
        FputsMethods
    };
    
    7 là dung lượng bộ nhớ cần thiết để lưu trữ trạng thái chương trình của bạn. Thật hữu ích khi mô-đun của bạn được sử dụng trong nhiều trình thông dịch phụ và mô-đun này có thể có các giá trị sau

    • Giá trị âm cho biết mô-đun này không hỗ trợ trình thông dịch phụ
    • Giá trị không âm cho phép khởi tạo lại mô-đun của bạn. Nó cũng chỉ định yêu cầu bộ nhớ của mô-đun của bạn sẽ được phân bổ cho mỗi phiên phiên dịch phụ

  5. static struct PyModuleDef fputsmodule = {
        PyModuleDef_HEAD_INIT,
        "fputs",
        "Python interface for the fputs C library function",
        -1,
        FputsMethods
    };
    
    8 là tham chiếu đến bảng phương pháp của bạn. Đây là mảng của
    static PyMethodDef FputsMethods[] = {
        {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
        {NULL, NULL, 0, NULL}
    };
    
    
    static struct PyModuleDef fputsmodule = {
        PyModuleDef_HEAD_INIT,
        "fputs",
        "Python interface for the fputs C library function",
        -1,
        FputsMethods
    };
    
    7 cấu trúc bạn đã xác định trước đó

Để biết thêm thông tin, hãy xem tài liệu Python chính thức trên

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
01

Bây giờ bạn đã xác định cấu trúc phương thức và mô-đun mở rộng Python C của mình, đã đến lúc đưa chúng vào sử dụng. Khi chương trình Python nhập mô-đun của bạn lần đầu tiên, nó sẽ gọi

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
02

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
0

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
01 ngầm thực hiện 3 điều khi được nêu dưới dạng kiểu trả về của hàm

  1. Nó hoàn toàn đặt kiểu trả về của hàm là
    static PyMethodDef FputsMethods[] = {
        {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
        {NULL, NULL, 0, NULL}
    };
    
    
    static struct PyModuleDef fputsmodule = {
        PyModuleDef_HEAD_INIT,
        "fputs",
        "Python interface for the fputs C library function",
        -1,
        FputsMethods
    };
    
    6
  2. Nó tuyên bố bất kỳ liên kết đặc biệt nào
  3. Nó khai báo hàm là extern “C. ” Trong trường hợp bạn đang sử dụng C++, nó sẽ báo cho trình biên dịch C++ không được xáo trộn tên trên các ký hiệu

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
05 sẽ trả về một đối tượng mô-đun mới kiểu
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
06. Đối với đối số, bạn sẽ chuyển địa chỉ của cấu trúc phương thức mà bạn đã xác định trước đó,
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
07

Ghi chú. Trong Python 3, hàm init của bạn phải trả về kiểu

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
06. Tuy nhiên, nếu bạn đang sử dụng Python 2, thì
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
01 khai báo kiểu trả về của hàm là
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
10

Loại bỏ các quảng cáo

Để tất cả chúng cùng nhau

Bây giờ bạn đã viết các phần cần thiết của mô-đun mở rộng Python C của mình, hãy lùi lại một bước để xem tất cả khớp với nhau như thế nào. Sơ đồ sau đây cho thấy các thành phần của mô-đun của bạn và cách chúng tương tác với trình thông dịch Python

Khi bạn nhập mô-đun mở rộng Python C của mình,

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
02 là phương thức đầu tiên được gọi. Tuy nhiên, trước khi một tham chiếu được trả về trình thông dịch Python, hàm sẽ thực hiện lệnh gọi tiếp theo tới
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
05. Điều này sẽ khởi tạo các cấu trúc
static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};
7 và
static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
7, chứa thông tin meta về mô-đun của bạn. Bạn nên chuẩn bị sẵn chúng vì bạn sẽ sử dụng chúng trong chức năng init của mình

Khi quá trình này hoàn tất, một tham chiếu đến đối tượng mô-đun cuối cùng sẽ được trả về trình thông dịch Python. Sơ đồ sau đây cho thấy luồng nội bộ của mô-đun của bạn

Đối tượng mô-đun được trả về bởi

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
05 có tham chiếu đến cấu trúc mô-đun
static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};
7, từ đó có tham chiếu đến bảng phương thức
static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
7. Khi bạn gọi một phương thức được xác định trong mô-đun mở rộng Python C của mình, trình thông dịch Python sẽ sử dụng đối tượng mô-đun và tất cả các tham chiếu mà nó mang để thực thi phương thức cụ thể. [Mặc dù đây không chính xác là cách trình thông dịch Python xử lý mọi thứ bên trong, nhưng nó sẽ cho bạn ý tưởng về cách thức hoạt động của nó. ]

Tương tự, bạn có thể truy cập nhiều phương thức và thuộc tính khác của mô-đun của mình, chẳng hạn như chuỗi tài liệu mô-đun hoặc chuỗi tài liệu phương thức. Chúng được xác định bên trong cấu trúc tương ứng của chúng

Bây giờ bạn đã hình dung được điều gì sẽ xảy ra khi bạn gọi

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7 từ trình thông dịch Python. Trình thông dịch sử dụng đối tượng mô-đun của bạn cũng như các tham chiếu mô-đun và phương thức để gọi phương thức. Cuối cùng, hãy xem cách trình thông dịch xử lý việc thực thi thực tế mô-đun mở rộng Python C của bạn

Khi

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
19 được gọi, chương trình sẽ thực hiện các bước sau

  1. Phân tích cú pháp các đối số bạn đã chuyển từ trình thông dịch Python bằng
     1static PyObject *method_fputs[PyObject *self, PyObject *args] {
     2    char *str, *filename = NULL;
     3    int bytes_copied = -1;
     4
     5    /* Parse arguments */
     6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     7        return NULL;
     8    }
     9
    10    /* Snip */
    
    0
  2. Chuyển các đối số này tới
     1#include 
     2
     3static PyObject *method_fputs[PyObject *self, PyObject *args] {
     4    char *str, *filename = NULL;
     5    int bytes_copied = -1;
     6
     7    /* Parse arguments */
     8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     9        return NULL;
    10    }
    11
    12    FILE *fp = fopen[filename, "w"];
    13    bytes_copied = fputs[str, fp];
    14    fclose[fp];
    15
    16    return PyLong_FromLong[bytes_copied];
    17}
    
    7, hàm thư viện C tạo thành mấu chốt của mô-đun của bạn
  3. Sử dụng
    #include 
    #include 
    #include 
    
    int main[] {
        FILE *fp = fopen["write.txt", "w"];
        fputs["Real Python!", fp];
        fclose[fp];
        return 1;
    }
    
    22 để trả về giá trị từ
     1#include 
     2
     3static PyObject *method_fputs[PyObject *self, PyObject *args] {
     4    char *str, *filename = NULL;
     5    int bytes_copied = -1;
     6
     7    /* Parse arguments */
     8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
     9        return NULL;
    10    }
    11
    12    FILE *fp = fopen[filename, "w"];
    13    bytes_copied = fputs[str, fp];
    14    fclose[fp];
    15
    16    return PyLong_FromLong[bytes_copied];
    17}
    
    7

Để xem các bước tương tự này trong mã, hãy xem lại

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
19

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
1

Tóm lại, phương thức của bạn sẽ phân tích cú pháp các đối số được chuyển đến mô-đun của bạn, gửi chúng tới

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7 và trả về kết quả

Đóng gói Mô-đun mở rộng Python C của bạn

Trước khi bạn có thể nhập mô-đun mới của mình, trước tiên bạn cần xây dựng mô-đun đó. Bạn có thể làm điều này bằng cách sử dụng gói Python

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
26

Bạn sẽ cần một tệp có tên là

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
27 để cài đặt ứng dụng của mình. Đối với hướng dẫn này, bạn sẽ tập trung vào phần dành riêng cho mô-đun mở rộng Python C. Để có thông tin sơ bộ đầy đủ, hãy xem Cách xuất bản Gói Python mã nguồn mở lên PyPI

Một tệp

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
27 tối thiểu cho mô-đun của bạn sẽ trông như thế này

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
2

Khối mã ở trên hiển thị các đối số tiêu chuẩn được chuyển đến

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
29. Hãy xem kỹ đối số vị trí cuối cùng,
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
30. Điều này lấy một danh sách các đối tượng của lớp
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
31. Một đối tượng của lớp
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
31 mô tả một mô-đun mở rộng C hoặc C++ duy nhất trong tập lệnh thiết lập. Tại đây, bạn chuyển hai đối số từ khóa cho hàm tạo của nó, cụ thể là

  • #include 
    #include 
    #include 
    
    int main[] {
        FILE *fp = fopen["write.txt", "w"];
        fputs["Real Python!", fp];
        fclose[fp];
        return 1;
    }
    
    33 là tên của mô-đun
  • #include 
    #include 
    #include 
    
    int main[] {
        FILE *fp = fopen["write.txt", "w"];
        fputs["Real Python!", fp];
        fclose[fp];
        return 1;
    }
    
    34 là danh sách các đường dẫn đến tệp có mã nguồn, liên quan đến tập lệnh thiết lập

Loại bỏ các quảng cáo

Xây dựng mô-đun của bạn

Bây giờ bạn đã có tệp

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
27 của mình, bạn có thể sử dụng nó để xây dựng mô-đun mở rộng Python C của mình. Bạn nên sử dụng môi trường ảo để tránh xung đột với môi trường Python của mình

Điều hướng đến thư mục chứa

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
27 và chạy lệnh sau

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
3

Lệnh này sẽ biên dịch và cài đặt mô-đun mở rộng Python C của bạn trong thư mục hiện tại. Nếu có bất kỳ lỗi hoặc cảnh báo nào, thì chương trình của bạn sẽ ném chúng ngay bây giờ. Đảm bảo bạn sửa những lỗi này trước khi cố gắng nhập mô-đun của mình

Theo mặc định, trình thông dịch Python sử dụng

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
37 để biên dịch mã C. Nếu bạn muốn sử dụng
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
38 hoặc bất kỳ trình biên dịch C nào khác cho công việc, thì bạn cần đặt biến môi trường
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
39 tương ứng, bên trong tập lệnh thiết lập hoặc trực tiếp trên dòng lệnh. Chẳng hạn, bạn có thể yêu cầu trình thông dịch Python sử dụng
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
38 để biên dịch và xây dựng mô-đun của mình theo cách này

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
4

Tuy nhiên, trình thông dịch Python sẽ tự động quay trở lại

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
38 nếu không có sẵn
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
37

Chạy mô-đun của bạn

Bây giờ mọi thứ đã sẵn sàng, đã đến lúc xem mô-đun của bạn hoạt động. Sau khi xây dựng thành công, hãy kích hoạt trình thông dịch để chạy thử mô-đun mở rộng Python C của bạn

>>>

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
5

Chức năng của bạn hoạt động như mong đợi. Bạn chuyển một chuỗi

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */
6 và một tệp để ghi chuỗi này vào,
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */
5. Lệnh gọi tới
 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7 trả về số byte được ghi vào tệp. Bạn có thể xác minh điều này bằng cách in nội dung của tệp

Đồng thời nhớ lại cách bạn chuyển một số đối số nhất định cho cấu trúc

static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};
7 và
static PyMethodDef FputsMethods[] = {
    {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
    {NULL, NULL, 0, NULL}
};


static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
7. Bạn có thể thấy từ kết quả này rằng Python đã sử dụng các cấu trúc này để gán những thứ như tên hàm và chuỗi tài liệu

Cùng với đó, bạn đã có một phiên bản cơ bản cho mô-đun của mình, nhưng bạn có thể làm được nhiều điều hơn nữa. Bạn có thể cải thiện mô-đun của mình bằng cách thêm những thứ như hằng số và ngoại lệ tùy chỉnh

Tăng ngoại lệ

Ngoại lệ Python rất khác với ngoại lệ C++. Nếu bạn muốn tăng ngoại lệ Python từ mô-đun mở rộng C của mình, thì bạn có thể sử dụng API Python để làm như vậy. Một số chức năng được cung cấp bởi API Python để tăng ngoại lệ như sau

Chức năngMô tả

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
48
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
49Có hai đối số. một đối số loại
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
06 chỉ định loại ngoại lệ và một thông báo tùy chỉnh để hiển thị cho người dùng
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
51
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
52Có hai đối số. một đối số loại
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
06 chỉ định loại ngoại lệ và một thông báo tùy chỉnh được định dạng để hiển thị cho người dùng
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
54
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
55Nhận hai đối số, cả hai đều thuộc loại
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
06. cái đầu tiên chỉ định loại ngoại lệ và cái thứ hai đặt một đối tượng Python tùy ý làm giá trị ngoại lệ

Bạn có thể sử dụng bất kỳ thứ nào trong số này để đưa ra một ngoại lệ. Tuy nhiên, sử dụng cái nào và khi nào phụ thuộc hoàn toàn vào yêu cầu của bạn. API Python có tất cả các loại được xác định trước là

 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */
9

Tăng ngoại lệ từ mã C

Mặc dù bạn không thể đưa ra các ngoại lệ trong C, nhưng API Python sẽ cho phép bạn đưa ra các ngoại lệ từ mô-đun mở rộng Python C của bạn. Hãy kiểm tra chức năng này bằng cách thêm

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
58 vào mã của bạn. Điều này sẽ đưa ra một ngoại lệ bất cứ khi nào độ dài của chuỗi được viết nhỏ hơn 10 ký tự

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
6

Ở đây, bạn kiểm tra độ dài của chuỗi đầu vào ngay sau khi bạn phân tích cú pháp các đối số và trước khi bạn gọi

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7. Nếu chuỗi do người dùng chuyển ngắn hơn 10 ký tự, thì chương trình của bạn sẽ tăng 10_______60 với thông báo tùy chỉnh. Việc thực thi chương trình dừng ngay khi xảy ra ngoại lệ

Lưu ý cách

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
19 trả về
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    FILE *fp = fopen[filename, "w"];
11    bytes_copied = fputs[str, fp];
12    fclose[fp];
13
14    return PyLong_FromLong[bytes_copied];
15}
8 sau khi tăng ngoại lệ. Điều này là do bất cứ khi nào bạn đưa ra một ngoại lệ bằng cách sử dụng
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
63, nó sẽ tự động đặt một mục nội bộ trong bảng ngoại lệ và trả về nó. Chức năng gọi không bắt buộc phải đặt lại mục nhập sau đó. Vì lý do này, hàm gọi trả về một giá trị cho biết lỗi, thường là
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    FILE *fp = fopen[filename, "w"];
11    bytes_copied = fputs[str, fp];
12    fclose[fp];
13
14    return PyLong_FromLong[bytes_copied];
15}
8 hoặc
static struct PyModuleDef fputsmodule = {
    PyModuleDef_HEAD_INIT,
    "fputs",
    "Python interface for the fputs C library function",
    -1,
    FputsMethods
};
7. [Điều này cũng sẽ giải thích lý do tại sao cần phải trả về
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    FILE *fp = fopen[filename, "w"];
11    bytes_copied = fputs[str, fp];
12    fclose[fp];
13
14    return PyLong_FromLong[bytes_copied];
15}
8 khi bạn phân tích các đối số trong
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
19 bằng cách sử dụng
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Parse arguments */
 6    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 7        return NULL;
 8    }
 9
10    /* Snip */
0. ]

Loại bỏ các quảng cáo

Tăng ngoại lệ tùy chỉnh

Bạn cũng có thể đưa ra các ngoại lệ tùy chỉnh trong mô-đun mở rộng Python C của mình. Tuy nhiên, mọi thứ hơi khác một chút. Trước đây, trong

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
01, bạn chỉ cần trả lại phiên bản được trả về bởi
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
70 và gọi nó là một ngày. Nhưng để người dùng mô-đun của bạn có thể truy cập ngoại lệ tùy chỉnh, bạn cần thêm ngoại lệ tùy chỉnh vào phiên bản mô-đun trước khi trả lại

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
7

Như trước đây, bạn bắt đầu bằng cách tạo một đối tượng mô-đun. Sau đó, bạn tạo một đối tượng ngoại lệ mới bằng cách sử dụng

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
71. Cái này lấy một chuỗi có dạng
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
72 làm tên của lớp ngoại lệ mà bạn muốn tạo. Chọn một cái gì đó mô tả để giúp người dùng dễ dàng diễn giải những gì đã thực sự sai

Tiếp theo, bạn thêm phần này vào đối tượng mô-đun của mình bằng cách sử dụng

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
73. Điều này lấy đối tượng mô-đun của bạn, tên của đối tượng mới được thêm vào và chính đối tượng ngoại lệ tùy chỉnh làm đối số. Cuối cùng, bạn trả lại đối tượng mô-đun của mình

Bây giờ bạn đã xác định một ngoại lệ tùy chỉnh để tăng ngoại lệ cho mô-đun của mình, bạn cần cập nhật

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
19 để nó tăng ngoại lệ thích hợp

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
8

Sau khi xây dựng mô-đun với các thay đổi mới, bạn có thể kiểm tra xem ngoại lệ tùy chỉnh của mình có hoạt động như mong đợi hay không bằng cách thử viết một chuỗi có độ dài dưới 10 ký tự

>>>

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
9

Khi bạn cố gắng viết một chuỗi có ít hơn 10 ký tự, ngoại lệ tùy chỉnh của bạn sẽ xuất hiện với thông báo giải thích điều gì đã xảy ra

Xác định hằng số

Có những trường hợp bạn sẽ muốn sử dụng hoặc xác định các hằng số trong mô-đun mở rộng Python C của mình. Điều này khá giống với cách bạn xác định các ngoại lệ tùy chỉnh trong phần trước. Bạn có thể xác định một hằng số mới và thêm nó vào phiên bản mô-đun của mình bằng cách sử dụng

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
75

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
0

Hàm API Python này có các đối số sau

  • Ví dụ về mô-đun của bạn
  • Tên của hằng số
  • Giá trị của hằng số

Bạn có thể làm tương tự với macro bằng cách sử dụng

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
76

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
1

Hàm này nhận các đối số sau

  • Ví dụ về mô-đun của bạn
  • Tên của macro đã được xác định

Ghi chú. Nếu bạn muốn thêm hằng số chuỗi hoặc macro vào mô-đun của mình, thì bạn có thể sử dụng lần lượt là

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
77 và
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
78

Mở trình thông dịch Python để xem các hằng số và macro của bạn có hoạt động như mong đợi không

>>>

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
2

Tại đây, bạn có thể thấy rằng các hằng số có thể truy cập được từ bên trong trình thông dịch Python

Loại bỏ các quảng cáo

Kiểm tra mô-đun của bạn

Bạn có thể kiểm tra mô-đun mở rộng Python C của mình giống như bất kỳ mô-đun Python nào khác. Điều này có thể được chứng minh bằng cách viết một hàm kiểm tra nhỏ cho

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
79

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
3

Trong kịch bản thử nghiệm ở trên, bạn sử dụng

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
80 để viết chuỗi
 1static PyObject *method_fputs[PyObject *self, PyObject *args] {
 2    char *str, *filename = NULL;
 3    int bytes_copied = -1;
 4
 5    /* Snip */
6 vào một tệp trống có tên
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
82. Sau đó, bạn đọc nội dung của tệp này và sử dụng một câu lệnh
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
83 để so sánh nó với những gì bạn đã viết ban đầu

Bạn có thể chạy bộ thử nghiệm này để đảm bảo rằng mô-đun của bạn đang hoạt động như mong đợi

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
4

Để có phần giới thiệu sâu hơn, hãy xem Bắt đầu với thử nghiệm trong Python

Xem xét các lựa chọn thay thế

Trong hướng dẫn này, bạn đã xây dựng giao diện cho chức năng thư viện C để hiểu cách viết các mô-đun mở rộng Python C. Tuy nhiên, có những lúc tất cả những gì bạn cần làm là gọi một số lệnh gọi hệ thống hoặc một vài hàm trong thư viện C và bạn muốn tránh phải viết hai ngôn ngữ khác nhau. Trong những trường hợp này, bạn có thể sử dụng các thư viện Python như

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
84 hoặc
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
85

Đây là các thư viện Hàm ngoại cho Python cung cấp quyền truy cập vào các hàm và kiểu dữ liệu của thư viện C. Mặc dù bản thân cộng đồng được phân chia theo thư viện nào là tốt nhất, nhưng cả hai đều có những lợi ích và hạn chế. Nói cách khác, một trong hai sẽ là lựa chọn tốt cho bất kỳ dự án cụ thể nào, nhưng có một số điều cần lưu ý khi bạn cần quyết định giữa hai bên.

  • Thư viện

    #include 
    #include 
    #include 
    
    int main[] {
        FILE *fp = fopen["write.txt", "w"];
        fputs["Real Python!", fp];
        fclose[fp];
        return 1;
    }
    
    84 được bao gồm trong thư viện chuẩn Python. Điều này rất quan trọng nếu bạn muốn tránh sự phụ thuộc bên ngoài. Nó cho phép bạn viết hàm bao cho các ngôn ngữ khác trong Python

  • Thư viện

    #include 
    #include 
    #include 
    
    int main[] {
        FILE *fp = fopen["write.txt", "w"];
        fputs["Real Python!", fp];
        fclose[fp];
        return 1;
    }
    
    85 chưa được đưa vào thư viện chuẩn. Đây có thể là một công cụ giải quyết cho dự án cụ thể của bạn. Nói chung, nó có bản chất Pythonic hơn, nhưng nó không xử lý tiền xử lý cho bạn

Để biết thêm thông tin về các thư viện này, hãy xem Mở rộng Python với Thư viện C và Mô-đun “ctypes” và Giao diện Python và C. Mô-đun CFFI

Ghi chú. Ngoài

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
84 và
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
85, còn có nhiều công cụ khác. Chẳng hạn, bạn cũng có thể sử dụng
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
90 và
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
91

Phần kết luận

Trong hướng dẫn này, bạn đã học cách viết giao diện Python bằng ngôn ngữ lập trình C bằng API Python. Bạn đã viết một trình bao bọc Python cho hàm thư viện C

 1#include 
 2
 3static PyObject *method_fputs[PyObject *self, PyObject *args] {
 4    char *str, *filename = NULL;
 5    int bytes_copied = -1;
 6
 7    /* Parse arguments */
 8    if[!PyArg_ParseTuple[args, "ss", &str, &filename]] {
 9        return NULL;
10    }
11
12    FILE *fp = fopen[filename, "w"];
13    bytes_copied = fputs[str, fp];
14    fclose[fp];
15
16    return PyLong_FromLong[bytes_copied];
17}
7. Bạn cũng đã thêm các hằng số và ngoại lệ tùy chỉnh vào mô-đun của mình trước khi xây dựng và thử nghiệm mô-đun đó

API Python cung cấp nhiều tính năng để viết các giao diện Python phức tạp bằng ngôn ngữ lập trình C. Đồng thời, các thư viện như

#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
85 hoặc
#include 
#include 
#include 

int main[] {
    FILE *fp = fopen["write.txt", "w"];
    fputs["Real Python!", fp];
    fclose[fp];
    return 1;
}
84 có thể giảm lượng chi phí liên quan đến việc viết các mô-đun mở rộng Python C. Hãy chắc chắn rằng bạn cân nhắc tất cả các yếu tố trước khi đưa ra quyết định

Đánh dấu là đã hoàn thành

🐍 Thủ thuật Python 💌

Nhận một Thủ thuật Python ngắn và hấp dẫn được gửi đến hộp thư đến của bạn vài ngày một lần. Không có thư rác bao giờ. Hủy đăng ký bất cứ lúc nào. Được quản lý bởi nhóm Real Python

Gửi cho tôi thủ thuật Python »

Về Prakash Đan Mạch

Tiếng Đan Mạch là một Pythonista cuồng nhiệt và viết cho Real Python

» Tìm hiểu thêm về tiếng Đan Mạch

Mỗi hướng dẫn tại Real Python được tạo bởi một nhóm các nhà phát triển để nó đáp ứng các tiêu chuẩn chất lượng cao của chúng tôi. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là

Aldren

Jim

Jaya

Joanna

Bậc thầy Kỹ năng Python trong thế giới thực Với quyền truy cập không giới hạn vào Python thực

Tham gia với chúng tôi và có quyền truy cập vào hàng nghìn hướng dẫn, khóa học video thực hành và cộng đồng các Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Chuyên gia Kỹ năng Python trong thế giới thực
Với quyền truy cập không giới hạn vào Python thực

Tham gia với chúng tôi và có quyền truy cập vào hàng ngàn hướng dẫn, khóa học video thực hành và cộng đồng Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Bạn nghĩ sao?

Đánh giá bài viết này

Tweet Chia sẻ Chia sẻ Email

Bài học số 1 hoặc điều yêu thích mà bạn đã học được là gì?

Mẹo bình luận. Những nhận xét hữu ích nhất là những nhận xét được viết với mục đích học hỏi hoặc giúp đỡ các sinh viên khác. và nhận câu trả lời cho các câu hỏi phổ biến trong cổng thông tin hỗ trợ của chúng tôi

Cython có nhanh bằng C không?

Cython có cùng tốc độ với chương trình C/C++ được điều chỉnh cẩn thận; . Tôi đã thực hiện nhiều điểm chuẩn của mã số cấp thấp khi triển khai SageMath [sử dụng Cython cho một số dòng mã 100K]

Làm cách nào để tạo mã C từ Python?

Csnake là gói Python 3 giúp bạn tạo mã C từ Python . Csnake cung cấp cho bạn API nhất quán và có ý kiến ​​giúp bạn cấu trúc mã Python tạo C của mình. Nó làm như vậy bằng cách cung cấp các lớp và hàm để tạo mọi cấu trúc ngôn ngữ C.

Tôi có thể biên dịch Python bằng GCC không?

Về lý thuyết plugin cho phép bạn viết các tập lệnh Python có thể chạy bên trong GCC khi nó biên dịch mã , hiển thị cấu trúc dữ liệu nội bộ của GCC dưới dạng .

Python có được biên dịch nhanh như C không?

Tuy nhiên, Python có một nhược điểm lớn. Nó chậm hơn nhiều so với các ngôn ngữ được biên dịch như C hoặc C++ .

Chủ Đề