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?
Để 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
Để 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
5 trong Python là một ví dụ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}
Đâ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áoViế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}
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ệnint fputs[const char *, FILE *]
Hàm này nhận hai đối số
9 là một mảng ký 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}
0 là con trỏ luồng tệp1static PyObject *method_fputs[PyObject *self, PyObject *args] { 2 char *str, *filename = NULL; 3 int bytes_copied = -1; 4 5 /* Snip */
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ôngViế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
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}
Đâ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
- Mở tệp
51static PyObject *method_fputs[PyObject *self, PyObject *args] { 2 char *str, *filename = NULL; 3 int bytes_copied = -1; 4 5 /* Snip */
- Viết chuỗi
6 vào tệp1static PyObject *method_fputs[PyObject *self, PyObject *args] { 2 char *str, *filename = NULL; 3 int bytes_copied = -1; 4 5 /* Snip */
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
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}
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
91static PyObject *method_fputs[PyObject *self, PyObject *args] { 2 char *str, *filename = NULL; 3 int bytes_copied = -1; 4 5 /* Snip */
01static 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 */
11static 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 */
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 */
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
7 là chuỗi bạn muốn ghi vào luồng tệp1static 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ào1static 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 */
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
1 thuộc loại1static 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}
91static PyObject *method_fputs[PyObject *self, PyObject *args] { 2 char *str, *filename = NULL; 3 int bytes_copied = -1; 4 5 /* Snip */
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án1static 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}
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
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}
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
0 và chuyển nó cho hàm1static PyObject *method_fputs[PyObject *self, PyObject *args] { 2 char *str, *filename = NULL; 3 int bytes_copied = -1; 4 5 /* Snip */
- Ở dòng 11, bạn gọi
7 với các đối số sau1#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 là chuỗi bạn muốn ghi vào tệp1static 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ượng1static 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}
0 bạn đã xác định ở dòng 101static PyObject *method_fputs[PyObject *self, PyObject *args] { 2 char *str, *filename = NULL; 3 int bytes_copied = -1; 4 5 /* Snip */
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 Pythonstatic 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
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
};
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 PythonLoại bỏ các quảng cáoViế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
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
};
Để 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ạnLý 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úcstatic 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
0 là tên người dùng sẽ viết để gọi chức năng cụ thể nàystatic 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ọistatic 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ểustatic PyMethodDef FputsMethods[] = { {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"}, {NULL, NULL, 0, NULL} };
6static 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 };
4 là đối tượng mô-đunstatic PyMethodDef FputsMethods[] = { {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"}, {NULL, NULL, 0, NULL} };
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ụng1static 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}
01static 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 */
- 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
static PyMethodDef FputsMethods[] = {
{"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"},
{NULL, NULL, 0, NULL}
};
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ô-đunstatic 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
0 là thành viên của loạistatic 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àystatic struct PyModuleDef fputsmodule = { PyModuleDef_HEAD_INIT, "fputs", "Python interface for the fputs C library function", -1, FputsMethods };
0 là tên của mô-đun mở rộng Python C của bạnstatic PyMethodDef FputsMethods[] = { {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"}, {NULL, NULL, 0, NULL} };
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
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ố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 như được hiển thị trong đoạn mã trên. Nó thuộc loại1#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. Bạn cũng có thể sử dụngstatic 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ìnhstatic 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ị saustatic struct PyModuleDef fputsmodule = { PyModuleDef_HEAD_INIT, "fputs", "Python interface for the fputs C library function", -1, FputsMethods };
- 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ụ
8 là tham chiếu đến bảng phương pháp của bạn. Đây là mảng củastatic 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 đó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 };
Để 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
#include
#include
#include
int main[] {
FILE *fp = fopen["write.txt", "w"];
fputs["Real Python!", fp];
fclose[fp];
return 1;
}
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- Nó hoàn toàn đặt kiểu trả về của hàm là
6static 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 };
- Nó tuyên bố bất kỳ liên kết đặc biệt nào
- 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;
}
07Ghi 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;
}
10Loạ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ìnhKhi 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ạnKhi
#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- 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
01static 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 */
- Chuyển các đối số này tới
7, hàm thư viện C tạo thành mấu chốt của mô-đun của bạn1#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}
- Sử dụng
22 để trả về giá trị từ#include #include #include int main[] { FILE *fp = fopen["write.txt", "w"]; fputs["Real Python!", fp]; fclose[fp]; return 1; }
71#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}
Để 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;
}
1Tó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;
}
26Bạ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 PyPIMộ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;
}
2Khố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à
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#include #include #include int main[] { FILE *fp = fopen["write.txt", "w"]; fputs["Real Python!", fp]; fclose[fp]; return 1; }
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;
}
3Lệ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;
}
4Tuy 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;
}
37Chạ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;
}
5Chứ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ệuCù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 */
9Tă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áoTă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;
}
7Như 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ự saiTiế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ìnhBâ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;
}
8Sau 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;
}
9Khi 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}
0Hà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}
1Hà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;
}
78Mở 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}
2Tạ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áoKiể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}
3Trong 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 đầuBạ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
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#include #include #include int main[] { FILE *fp = fopen["write.txt", "w"]; fputs["Real Python!", fp]; fclose[fp]; return 1; }
Thư viện
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#include #include #include int main[] { FILE *fp = fopen["write.txt", "w"]; fputs["Real Python!", fp]; fclose[fp]; return 1; }
Để 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;
}
91Phầ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ạchMỗ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ẻ EmailBà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