Bạn có phải là nhà phát triển Python có thư viện C hoặc C++ mà bạn muốn sử dụng từ Python không? . Xuyên suốt hướng dẫn này, bạn sẽ thấy tổng quan về một số công cụ bạn có thể sử dụng để tạo các liên kết Python
Trong hướng dẫn này, bạn sẽ tìm hiểu về
- Tại sao bạn muốn gọi C hoặc C++ từ Python
- Cách truyền dữ liệu giữa C và Python
- Những công cụ và phương pháp nào có thể giúp bạn tạo các liên kết Python
Hướng dẫn này dành cho các nhà phát triển Python trung cấp. Nó giả định kiến thức cơ bản về Python và một số hiểu biết về các hàm và kiểu dữ liệu trong C hoặc C++. Bạn có thể lấy tất cả mã ví dụ mà bạn sẽ thấy trong hướng dẫn này bằng cách nhấp vào liên kết bên dưới
Nhận mã mẫu. Nhấp vào đây để lấy mã mẫu mà bạn sẽ sử dụng để tìm hiểu về Python Bindings trong hướng dẫn này
Hãy đi sâu vào xem xét các ràng buộc Python
Tổng quan về ràng buộc Python
Trước khi bạn tìm hiểu cách gọi C từ Python, bạn nên dành chút thời gian tìm hiểu lý do tại sao. Có một số tình huống tạo các liên kết Python để gọi thư viện C là một ý tưởng tuyệt vời
Bạn đã có một thư viện lớn, đã được thử nghiệm, ổn định được viết bằng C++ mà bạn muốn tận dụng bằng Python. Đây có thể là thư viện giao tiếp hoặc thư viện để nói chuyện với một phần cứng cụ thể. Nó làm gì không quan trọng
Bạn muốn tăng tốc một phần cụ thể trong mã Python của mình bằng cách chuyển đổi một phần quan trọng sang C. C không chỉ có tốc độ thực thi nhanh hơn mà còn cho phép bạn thoát khỏi những hạn chế của GIL, miễn là bạn cẩn thận
Bạn muốn sử dụng các công cụ kiểm tra Python để thực hiện kiểm tra quy mô lớn cho hệ thống của họ
Tất cả những điều trên là những lý do tuyệt vời để học cách tạo các liên kết Python để giao tiếp với thư viện C của bạn
Ghi chú. Xuyên suốt hướng dẫn này, bạn sẽ tạo các ràng buộc Python cho cả C và C++. Hầu hết các khái niệm chung áp dụng cho cả hai ngôn ngữ và vì vậy C sẽ được sử dụng trừ khi có sự khác biệt cụ thể giữa hai ngôn ngữ. Nói chung, mỗi công cụ sẽ hỗ trợ C hoặc C++, nhưng không hỗ trợ cả hai
Bắt đầu nào
Loại bỏ các quảng cáoLoại dữ liệu Marshalling
Chờ đợi. Trước khi bạn bắt đầu viết các liên kết Python, hãy xem cách Python và C lưu trữ dữ liệu và loại sự cố nào sẽ gây ra. Đầu tiên, hãy định nghĩa soái ca. Khái niệm này được Wikipedia định nghĩa như sau
Quá trình chuyển đổi biểu diễn bộ nhớ của một đối tượng thành định dạng dữ liệu phù hợp để lưu trữ hoặc truyền tải. [Nguồn]
Đối với mục đích của bạn, sắp xếp thứ tự là những gì các liên kết Python đang thực hiện khi chúng chuẩn bị dữ liệu để chuyển dữ liệu đó từ Python sang C hoặc ngược lại. Các ràng buộc Python cần thực hiện sắp xếp lại vì Python và C lưu trữ dữ liệu theo những cách khác nhau. C lưu trữ dữ liệu ở dạng nhỏ gọn nhất trong bộ nhớ có thể. Nếu bạn sử dụng
$ invoke --list
Available tasks:
all Build and run all tests
build-cffi Build the CFFI Python bindings
build-cmult Build the shared library for the sample C code
build-cppmult Build the shared library for the sample C++ code
build-cython Build the cython extension module
build-pybind11 Build the pybind11 wrapper library
clean Remove any built objects
test-cffi Run the script to test CFFI
test-ctypes Run the script to test ctypes
test-cython Run the script to test Cython
test-pybind11 Run the script to test PyBind11
7, thì nó sẽ chỉ sử dụng tổng cộng 8 bit bộ nhớMặt khác, trong Python, mọi thứ đều là một đối tượng. Điều này có nghĩa là mỗi số nguyên sử dụng một số byte trong bộ nhớ. Có bao nhiêu tùy thuộc vào phiên bản Python bạn đang chạy, hệ điều hành của bạn và các yếu tố khác. Điều này có nghĩa là các ràng buộc Python của bạn sẽ cần chuyển đổi số nguyên C thành số nguyên Python cho mỗi số nguyên được truyền qua ranh giới
Các loại dữ liệu khác có mối quan hệ tương tự giữa hai ngôn ngữ. Hãy lần lượt xem xét từng
cửa hàng đếm số. Python lưu trữ các số nguyên với độ chính xác tùy ý, nghĩa là bạn có thể lưu trữ các số rất, rất, lớn. C chỉ định kích thước chính xác của số nguyên. Bạn cần lưu ý về kích thước dữ liệu khi di chuyển giữa các ngôn ngữ để ngăn các giá trị số nguyên Python làm tràn các biến số nguyên C
là những số có một chữ số thập phân. Python có thể lưu trữ các số dấu phẩy động lớn hơn [và nhỏ hơn nhiều] so với C. Điều này có nghĩa là bạn cũng sẽ phải chú ý đến các giá trị đó để đảm bảo chúng nằm trong phạm vi
Số phức là số có phần ảo. Mặc dù Python có các số phức tích hợp và C có các số phức, nhưng không có phương thức tích hợp nào để sắp xếp lại giữa chúng. Để sắp xếp các số phức, bạn sẽ cần xây dựng một
8 hoặc$ invoke --list Available tasks: all Build and run all tests build-cffi Build the CFFI Python bindings build-cmult Build the shared library for the sample C code build-cppmult Build the shared library for the sample C++ code build-cython Build the cython extension module build-pybind11 Build the pybind11 wrapper library clean Remove any built objects test-cffi Run the script to test CFFI test-ctypes Run the script to test ctypes test-cython Run the script to test Cython test-pybind11 Run the script to test PyBind11
9 trong mã C để quản lý chúng$ invoke --list Available tasks: all Build and run all tests build-cffi Build the CFFI Python bindings build-cmult Build the shared library for the sample C code build-cppmult Build the shared library for the sample C++ code build-cython Build the cython extension module build-pybind11 Build the pybind11 wrapper library clean Remove any built objects test-cffi Run the script to test CFFI test-ctypes Run the script to test ctypes test-cython Run the script to test Cython test-pybind11 Run the script to test PyBind11
là các dãy ký tự. Vì là một kiểu dữ liệu phổ biến như vậy, các chuỗi sẽ tỏ ra khá phức tạp khi bạn tạo các liên kết Python. Cũng như các kiểu dữ liệu khác, Python và C lưu trữ các chuỗi ở các định dạng khá khác nhau. [Không giống như các kiểu dữ liệu khác, đây là lĩnh vực mà C và C++ cũng khác nhau, điều này làm tăng thêm sự thú vị. ] Mỗi giải pháp bạn sẽ kiểm tra có các phương pháp hơi khác nhau để xử lý các chuỗi
Biến Boolean chỉ có thể có hai giá trị. Vì chúng được hỗ trợ trong C, nên việc sắp xếp chúng sẽ khá đơn giản
Bên cạnh việc chuyển đổi loại dữ liệu, có những vấn đề khác mà bạn cần phải suy nghĩ khi xây dựng các liên kết Python của mình. Hãy tiếp tục khám phá chúng
Hiểu các giá trị có thể thay đổi và bất biến
Ngoài tất cả các loại dữ liệu này, bạn cũng sẽ phải biết cách các đối tượng Python có thể thay đổi hoặc không thay đổi. C có một khái niệm tương tự với các tham số chức năng khi nói về truyền theo giá trị hoặc truyền theo tham chiếu. Trong C, tất cả các tham số đều là giá trị truyền qua. Nếu bạn muốn cho phép một hàm thay đổi một biến trong trình gọi, thì bạn cần chuyển một con trỏ tới biến đó
Bạn có thể tự hỏi liệu bạn có thể khắc phục hạn chế bất biến bằng cách chuyển một đối tượng bất biến sang C bằng cách sử dụng một con trỏ hay không. Trừ khi bạn đi đến những điểm cực đoan xấu xí và không di động, Python sẽ không cung cấp cho bạn một con trỏ tới một đối tượng, vì vậy điều này không hoạt động. Nếu bạn muốn sửa đổi một đối tượng Python trong C, thì bạn sẽ cần thực hiện thêm các bước để đạt được điều này. Các bước này sẽ phụ thuộc vào công cụ bạn sử dụng, như bạn sẽ thấy bên dưới
Vì vậy, bạn có thể thêm tính bất biến vào danh sách kiểm tra các mục cần xem xét khi tạo các ràng buộc Python. Điểm dừng cuối cùng của bạn trong hành trình tạo danh sách kiểm tra này là cách xử lý các cách khác nhau mà Python và C xử lý với việc quản lý bộ nhớ
Quản lý bộ nhớ
C và Python quản lý bộ nhớ khác nhau. Trong C, nhà phát triển phải quản lý tất cả các phân bổ bộ nhớ và đảm bảo chúng được giải phóng một lần và chỉ một lần. Python sẽ giải quyết vấn đề này cho bạn bằng cách sử dụng trình thu gom rác
Mặc dù mỗi cách tiếp cận này đều có những ưu điểm của nó, nhưng nó lại tạo thêm một vấn đề khó khăn trong việc tạo các ràng buộc Python. Bạn sẽ cần biết vị trí bộ nhớ cho từng đối tượng được phân bổ và đảm bảo rằng bộ nhớ chỉ được giải phóng ở cùng một phía của rào cản ngôn ngữ
Ví dụ: một đối tượng Python được tạo khi bạn đặt
// cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
0. Bộ nhớ cho điều này được phân bổ ở phía Python và cần được thu gom rác. May mắn thay, với các đối tượng Python, thật khó để làm bất cứ điều gì khác. Hãy xem điều ngược lại trong C, nơi bạn cấp phát trực tiếp một khối bộ nhớint* iPtr = [int*]malloc[sizeof[int]];
Khi bạn làm điều này, bạn cần đảm bảo rằng con trỏ này được giải phóng trong C. Điều này có thể có nghĩa là thêm mã theo cách thủ công vào các liên kết Python của bạn để thực hiện việc này
Điều đó làm tròn danh sách kiểm tra của bạn về các chủ đề chung. Hãy bắt đầu thiết lập hệ thống của bạn để bạn có thể viết một số mã
Thiết lập môi trường của bạn
Đối với hướng dẫn này, bạn sẽ sử dụng các thư viện C và C++ có sẵn từ repo Real Python GitHub để hiển thị bản kiểm tra của từng công cụ. Mục đích là bạn sẽ có thể sử dụng những ý tưởng này cho bất kỳ thư viện C nào. Để làm theo cùng với tất cả các ví dụ ở đây, bạn sẽ cần phải có những điều sau đây
- Một thư viện C++ được cài đặt và kiến thức về đường dẫn để gọi dòng lệnh
- Công cụ phát triển Python
- Đối với Linux, đây là gói
1 hoặc// cmult.c float cmult[int int_param, float float_param] { float return_value = int_param * float_param; printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param, float_param, return_value]; return return_value; }
2, tùy thuộc vào bản phân phối của bạn// cmult.c float cmult[int int_param, float float_param] { float return_value = int_param * float_param; printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param, float_param, return_value]; return return_value; }
- Đối với Windows, có
- Đối với Linux, đây là gói
- Trăn 3. 6 hoặc cao hơn
- Môi trường ảo [được khuyến nghị, nhưng không bắt buộc]
- Công cụ
3// cmult.c float cmult[int int_param, float float_param] { float return_value = int_param * float_param; printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param, float_param, return_value]; return return_value; }
Cái cuối cùng có thể là mới đối với bạn, vì vậy hãy xem xét kỹ hơn về nó
Loại bỏ các quảng cáoSử dụng Công cụ // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3
// cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
// cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3 là công cụ bạn sẽ sử dụng để xây dựng và kiểm tra các liên kết Python của mình trong hướng dẫn này. Nó có mục đích tương tự như // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
6 nhưng sử dụng Python thay vì Makefiles. Bạn sẽ cần cài đặt // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3 trong môi trường ảo của mình bằng cách sử dụng // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
8$ python3 -m pip install invoke
Để chạy nó, bạn gõ
// cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3 theo sau là nhiệm vụ bạn muốn thực hiện$ invoke build-cmult
==================================================
= Building C Library
* Complete
Để xem nhiệm vụ nào khả dụng, bạn sử dụng tùy chọn
# ctypes_test.py
import ctypes
import pathlib
if __name__ == "__main__":
# Load the shared library into ctypes
libname = pathlib.Path[].absolute[] / "libcmult.so"
c_lib = ctypes.CDLL[libname]
0$ invoke --list
Available tasks:
all Build and run all tests
build-cffi Build the CFFI Python bindings
build-cmult Build the shared library for the sample C code
build-cppmult Build the shared library for the sample C++ code
build-cython Build the cython extension module
build-pybind11 Build the pybind11 wrapper library
clean Remove any built objects
test-cffi Run the script to test CFFI
test-ctypes Run the script to test ctypes
test-cython Run the script to test Cython
test-pybind11 Run the script to test PyBind11
Lưu ý rằng khi bạn xem tệp
# ctypes_test.py
import ctypes
import pathlib
if __name__ == "__main__":
# Load the shared library into ctypes
libname = pathlib.Path[].absolute[] / "libcmult.so"
c_lib = ctypes.CDLL[libname]
1 nơi các nhiệm vụ của // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3 được xác định, bạn sẽ thấy tên của nhiệm vụ thứ hai được liệt kê là # ctypes_test.py
import ctypes
import pathlib
if __name__ == "__main__":
# Load the shared library into ctypes
libname = pathlib.Path[].absolute[] / "libcmult.so"
c_lib = ctypes.CDLL[libname]
3. Tuy nhiên, đầu ra từ # ctypes_test.py
import ctypes
import pathlib
if __name__ == "__main__":
# Load the shared library into ctypes
libname = pathlib.Path[].absolute[] / "libcmult.so"
c_lib = ctypes.CDLL[libname]
0 cho thấy nó là # ctypes_test.py
import ctypes
import pathlib
if __name__ == "__main__":
# Load the shared library into ctypes
libname = pathlib.Path[].absolute[] / "libcmult.so"
c_lib = ctypes.CDLL[libname]
5. Dấu trừ [# ctypes_test.py
import ctypes
import pathlib
if __name__ == "__main__":
# Load the shared library into ctypes
libname = pathlib.Path[].absolute[] / "libcmult.so"
c_lib = ctypes.CDLL[libname]
6] không thể được sử dụng như một phần của tên Python, vì vậy tệp sử dụng dấu gạch dưới [# ctypes_test.py
import ctypes
import pathlib
if __name__ == "__main__":
# Load the shared library into ctypes
libname = pathlib.Path[].absolute[] / "libcmult.so"
c_lib = ctypes.CDLL[libname]
7] để thay thếĐối với mỗi công cụ mà bạn sẽ kiểm tra, sẽ có một nhiệm vụ
# ctypes_test.py
import ctypes
import pathlib
if __name__ == "__main__":
# Load the shared library into ctypes
libname = pathlib.Path[].absolute[] / "libcmult.so"
c_lib = ctypes.CDLL[libname]
8 và một nhiệm vụ # ctypes_test.py
import ctypes
import pathlib
if __name__ == "__main__":
# Load the shared library into ctypes
libname = pathlib.Path[].absolute[] / "libcmult.so"
c_lib = ctypes.CDLL[libname]
9 được xác định. Ví dụ: để chạy mã cho // cmult.h
float cmult[int int_param, float float_param];
0, bạn có thể nhập // cmult.h
float cmult[int int_param, float float_param];
1. Một ngoại lệ là // cmult.h
float cmult[int int_param, float float_param];
2, vì không có giai đoạn xây dựng nào cho // cmult.h
float cmult[int int_param, float float_param];
2. Ngoài ra, có hai nhiệm vụ đặc biệt được thêm vào để thuận tiện
4 chạy các tác vụ xây dựng và thử nghiệm cho tất cả các công cụ// cmult.h float cmult[int int_param, float float_param];
5 xóa mọi tệp được tạo// cmult.h float cmult[int int_param, float float_param];
Bây giờ bạn đã có cảm giác về cách chạy mã, hãy xem qua mã C mà bạn sẽ gói gọn trước khi nhấn vào phần tổng quan về công cụ
Nguồn C hoặc C++
Trong mỗi phần ví dụ bên dưới, bạn sẽ tạo các liên kết Python cho cùng một chức năng trong C hoặc C++. Các phần này nhằm mục đích cung cấp cho bạn cảm nhận về giao diện của từng phương thức, thay vì hướng dẫn chuyên sâu về công cụ đó, vì vậy chức năng bạn sẽ gói gọn là nhỏ. Hàm mà bạn sẽ tạo các ràng buộc Python để lấy một số là _____27_______6 và _____________7 làm tham số đầu vào và trả về một ____27_______7 là tích của hai số
// cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
Các hàm C và C++ gần như giống hệt nhau, với tên nhỏ và chuỗi khác biệt giữa chúng. Bạn có thể lấy một bản sao của tất cả mã bằng cách nhấp vào liên kết bên dưới
Nhận mã mẫu. Nhấp vào đây để lấy mã mẫu mà bạn sẽ sử dụng để tìm hiểu về Python Bindings trong hướng dẫn này
Bây giờ bạn đã nhân bản repo và các công cụ của bạn đã được cài đặt, bạn có thể xây dựng và kiểm tra các công cụ. Vì vậy, hãy đi sâu vào từng phần bên dưới
// cmult.h
float cmult[int int_param, float float_param];
2
// cmult.h
float cmult[int int_param, float float_param];
Bạn sẽ bắt đầu với
// cmult.h
float cmult[int int_param, float float_param];
2, đây là một công cụ trong thư viện tiêu chuẩn để tạo các liên kết Python. Nó cung cấp bộ công cụ cấp thấp để tải các thư viện dùng chung và sắp xếp dữ liệu giữa Python và CNó được cài đặt như thế nào
Một trong những lợi thế lớn của
// cmult.h
float cmult[int int_param, float float_param];
2 là nó là một phần của thư viện chuẩn Python. Nó đã được thêm vào Python phiên bản 2. 5, vì vậy rất có thể bạn đã có nó. Bạn có thể x, y = 6, 2.3
answer = c_lib.cmult[x, y]
2 giống như bạn làm với các mô-đun x, y = 6, 2.3
answer = c_lib.cmult[x, y]
3 hoặc x, y = 6, 2.3
answer = c_lib.cmult[x, y]
4Loại bỏ các quảng cáoGọi hàm
Tất cả mã để tải thư viện C của bạn và gọi hàm sẽ có trong chương trình Python của bạn. Điều này thật tuyệt vì không có bước bổ sung nào trong quy trình của bạn. Bạn chỉ cần chạy chương trình của mình và mọi thứ đã được lo liệu. Để tạo các liên kết Python của bạn trong
// cmult.h
float cmult[int int_param, float float_param];
2, bạn cần thực hiện các bước sau- Tải thư viện của bạn
- Gói một số tham số đầu vào của bạn
- Nói với
2 kiểu trả về của hàm của bạn// cmult.h float cmult[int int_param, float float_param];
Bạn sẽ lần lượt xem xét từng vấn đề này
Đang tải thư viện
// cmult.h
float cmult[int int_param, float float_param];
2 cung cấp một số cách để bạn thực hiện, một số trong đó dành riêng cho nền tảng. Ví dụ của bạn, bạn sẽ tạo một đối tượng x, y = 6, 2.3
answer = c_lib.cmult[x, y]
8 trực tiếp bằng cách chuyển vào đường dẫn đầy đủ đến thư viện dùng chung mà bạn muốn# ctypes_test.py
import ctypes
import pathlib
if __name__ == "__main__":
# Load the shared library into ctypes
libname = pathlib.Path[].absolute[] / "libcmult.so"
c_lib = ctypes.CDLL[libname]
Điều này sẽ hoạt động đối với các trường hợp khi thư viện dùng chung nằm trong cùng thư mục với tập lệnh Python của bạn, nhưng hãy cẩn thận khi bạn cố tải các thư viện từ các gói khác với các liên kết Python của bạn. Có nhiều chi tiết về cách tải thư viện và tìm đường dẫn trong tài liệu
// cmult.h
float cmult[int int_param, float float_param];
2 dành cho nền tảng và tình huống cụ thểGHI CHÚ. Nhiều sự cố dành riêng cho nền tảng có thể phát sinh trong quá trình tải thư viện. Tốt nhất là thực hiện các thay đổi gia tăng sau khi bạn có một ví dụ hoạt động
Bây giờ bạn đã tải thư viện vào Python, bạn có thể thử gọi nó
Gọi chức năng của bạn
Hãy nhớ rằng nguyên mẫu hàm cho hàm C của bạn như sau
// cmult.h
float cmult[int int_param, float float_param];
Bạn cần chuyển vào một số nguyên và một số float và có thể mong đợi nhận được một số float được trả về. Số nguyên và số float có hỗ trợ riêng trong cả Python và C, vì vậy bạn mong đợi trường hợp này sẽ hoạt động với các giá trị hợp lý
Khi bạn đã tải thư viện vào các liên kết Python của mình, hàm sẽ là một thuộc tính của
$ invoke test-ctypes
Traceback [most recent call last]:
File "ctypes_test.py", line 16, in
answer = c_lib.cmult[x, y]
ctypes.ArgumentError: argument 2: : Don't know how to convert parameter 2
0, là đối tượng $ invoke test-ctypes
Traceback [most recent call last]:
File "ctypes_test.py", line 16, in
answer = c_lib.cmult[x, y]
ctypes.ArgumentError: argument 2: : Don't know how to convert parameter 2
1 mà bạn đã tạo trước đó. Bạn có thể thử gọi nó như thế nàyx, y = 6, 2.3
answer = c_lib.cmult[x, y]
Ối. Điều này không hoạt động. Dòng này được nhận xét trong ví dụ repo vì nó không thành công. Nếu bạn cố chạy với lệnh gọi đó, thì Python sẽ báo lỗi
$ invoke test-ctypes
Traceback [most recent call last]:
File "ctypes_test.py", line 16, in
answer = c_lib.cmult[x, y]
ctypes.ArgumentError: argument 2: : Don't know how to convert parameter 2
Có vẻ như bạn cần thông báo cho
// cmult.h
float cmult[int int_param, float float_param];
2 về bất kỳ tham số nào không phải là số nguyên. // cmult.h
float cmult[int int_param, float float_param];
2 không biết gì về chức năng trừ khi bạn nói rõ ràng. Bất kỳ tham số nào không được đánh dấu khác được coi là số nguyên. // cmult.h
float cmult[int int_param, float float_param];
2 không biết cách chuyển đổi giá trị $ invoke test-ctypes
Traceback [most recent call last]:
File "ctypes_test.py", line 16, in
answer = c_lib.cmult[x, y]
ctypes.ArgumentError: argument 2: : Don't know how to convert parameter 2
5 được lưu trữ trong $ invoke test-ctypes
Traceback [most recent call last]:
File "ctypes_test.py", line 16, in
answer = c_lib.cmult[x, y]
ctypes.ArgumentError: argument 2: : Don't know how to convert parameter 2
6 thành số nguyên nên không thành côngĐể khắc phục điều này, bạn cần tạo một số
$ invoke test-ctypes
Traceback [most recent call last]:
File "ctypes_test.py", line 16, in
answer = c_lib.cmult[x, y]
ctypes.ArgumentError: argument 2: : Don't know how to convert parameter 2
7 từ số. Bạn có thể làm điều đó trong dòng mà bạn đang gọi hàm# ctypes_test.py
answer = c_lib.cmult[x, ctypes.c_float[y]]
print[f" In Python: int: {x} float {y:.1f} return val {answer:.1f}"]
Bây giờ, khi bạn chạy mã này, nó sẽ trả về tích của hai số bạn đã nhập
$ python3 -m pip install invoke
0Đợi một chút…
$ invoke test-ctypes
Traceback [most recent call last]:
File "ctypes_test.py", line 16, in
answer = c_lib.cmult[x, y]
ctypes.ArgumentError: argument 2: : Don't know how to convert parameter 2
8 nhân với $ invoke test-ctypes
Traceback [most recent call last]:
File "ctypes_test.py", line 16, in
answer = c_lib.cmult[x, y]
ctypes.ArgumentError: argument 2: : Don't know how to convert parameter 2
5 không phải là # ctypes_test.py
answer = c_lib.cmult[x, ctypes.c_float[y]]
print[f" In Python: int: {x} float {y:.1f} return val {answer:.1f}"]
0Hóa ra, giống như các tham số đầu vào,
// cmult.h
float cmult[int int_param, float float_param];
2 giả sử hàm của bạn trả về một giá trị // cmult.h
float cmult[int int_param, float float_param];
6. Trên thực tế, hàm của bạn trả về một // cmult.h
float cmult[int int_param, float float_param];
7, đang được sắp xếp không chính xác. Cũng giống như tham số đầu vào, bạn cần yêu cầu // cmult.h
float cmult[int int_param, float float_param];
2 sử dụng một loại khác. Cú pháp ở đây hơi khác một chút$ python3 -m pip install invoke
1Điều đó sẽ làm các trick. Hãy chạy toàn bộ mục tiêu
# ctypes_test.py
answer = c_lib.cmult[x, ctypes.c_float[y]]
print[f" In Python: int: {x} float {y:.1f} return val {answer:.1f}"]
5 và xem những gì bạn có. Hãy nhớ rằng, phần đầu tiên của đầu ra là trước khi bạn sửa # ctypes_test.py
answer = c_lib.cmult[x, ctypes.c_float[y]]
print[f" In Python: int: {x} float {y:.1f} return val {answer:.1f}"]
6 của hàm thành float$ python3 -m pip install invoke
2Cái đó tốt hơn. Trong khi phiên bản đầu tiên, chưa được chỉnh sửa trả về giá trị sai, phiên bản cố định của bạn phù hợp với hàm C. Cả C và Python đều nhận được kết quả giống nhau. Bây giờ nó đang hoạt động, hãy xem lý do tại sao bạn có thể muốn hoặc không muốn sử dụng
// cmult.h
float cmult[int int_param, float float_param];
2Loại bỏ các quảng cáoĐiểm mạnh và điểm yếu
Ưu điểm lớn nhất của
// cmult.h
float cmult[int int_param, float float_param];
2 so với các công cụ khác mà bạn sẽ kiểm tra ở đây là nó được tích hợp vào thư viện tiêu chuẩn. Nó cũng không yêu cầu thêm bước nào, vì tất cả công việc được thực hiện như một phần của chương trình Python của bạnNgoài ra, các khái niệm được sử dụng ở mức độ thấp, giúp cho các bài tập như bài bạn vừa làm có thể quản lý được. Tuy nhiên, các tác vụ phức tạp hơn trở nên cồng kềnh do thiếu tự động hóa. Trong phần tiếp theo, bạn sẽ thấy một công cụ bổ sung một số quy trình tự động hóa
// cmult.h
float cmult[int int_param, float float_param];
0
// cmult.h
float cmult[int int_param, float float_param];
// cmult.h
float cmult[int int_param, float float_param];
0 là Giao diện chức năng ngoại C cho Python. Cần một cách tiếp cận tự động hơn để tạo các liên kết Python. // cmult.h
float cmult[int int_param, float float_param];
0 có nhiều cách để bạn có thể xây dựng và sử dụng các liên kết Python của mình. Có hai tùy chọn khác nhau để chọn, cung cấp cho bạn bốn chế độ có thểABI so với API. Chế độ API sử dụng trình biên dịch C để tạo mô-đun Python đầy đủ, trong khi chế độ ABI tải thư viện dùng chung và tương tác trực tiếp với nó. Nếu không chạy trình biên dịch, việc sửa các cấu trúc và tham số sẽ dễ bị lỗi. Tài liệu rất khuyến nghị sử dụng chế độ API
nội tuyến so với ngoại tuyến. Sự khác biệt giữa hai chế độ này là sự đánh đổi giữa tốc độ và sự tiện lợi
- Chế độ nội tuyến biên dịch các liên kết Python mỗi khi tập lệnh của bạn chạy. Điều này rất tiện lợi vì bạn không cần thêm bước xây dựng. Tuy nhiên, nó làm chậm chương trình của bạn
- Chế độ ngoại tuyến yêu cầu thêm một bước để tạo các liên kết Python một lần và sau đó sử dụng chúng mỗi khi chương trình được chạy. Điều này nhanh hơn nhiều, nhưng điều đó có thể không quan trọng đối với ứng dụng của bạn
Đối với ví dụ này, bạn sẽ sử dụng chế độ ngoại tuyến API, chế độ này tạo ra mã nhanh nhất và nói chung, trông giống với các liên kết Python khác mà bạn sẽ tạo sau trong hướng dẫn này
Nó được cài đặt như thế nào
Vì
// cmult.h
float cmult[int int_param, float float_param];
0 không phải là một phần của thư viện tiêu chuẩn, bạn sẽ cần cài đặt nó trên máy của mình. Bạn nên tạo một môi trường ảo cho việc này. May mắn thay, // cmult.h
float cmult[int int_param, float float_param];
0 cài đặt với // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
8$ python3 -m pip install invoke
3Điều này sẽ cài đặt gói vào môi trường ảo của bạn. Nếu bạn đã cài đặt từ
$ python3 -m pip install invoke
05, thì điều này nên được quan tâm. Bạn có thể xem $ python3 -m pip install invoke
05 bằng cách truy cập repo tại liên kết bên dướiNhận mã mẫu. Nhấp vào đây để lấy mã mẫu mà bạn sẽ sử dụng để tìm hiểu về Python Bindings trong hướng dẫn này
Bây giờ bạn đã cài đặt
// cmult.h
float cmult[int int_param, float float_param];
0, đã đến lúc sử dụng nóGọi hàm
Không giống như
// cmult.h
float cmult[int int_param, float float_param];
2, với // cmult.h
float cmult[int int_param, float float_param];
0 bạn đang tạo một mô-đun Python đầy đủ. Bạn sẽ có thể x, y = 6, 2.3
answer = c_lib.cmult[x, y]
2 mô-đun giống như bất kỳ mô-đun nào khác trong thư viện tiêu chuẩn. Có một số công việc bổ sung mà bạn sẽ phải làm để xây dựng mô-đun Python của mình. Để sử dụng các ràng buộc // cmult.h
float cmult[int int_param, float float_param];
0 Python của bạn, bạn cần thực hiện các bước sau- Viết một số mã Python mô tả các ràng buộc
- Chạy mã đó để tạo mô-đun có thể tải
- Sửa đổi mã gọi để nhập và sử dụng mô-đun mới tạo của bạn
Điều đó có vẻ tốn nhiều công sức, nhưng bạn sẽ thực hiện từng bước này và xem nó hoạt động như thế nào
Viết các ràng buộc
// cmult.h
float cmult[int int_param, float float_param];
0 cung cấp các phương thức đọc tệp tiêu đề C để thực hiện hầu hết công việc khi tạo các liên kết Python. Trong tài liệu về // cmult.h
float cmult[int int_param, float float_param];
0, mã để thực hiện việc này được đặt trong một tệp Python riêng. Đối với ví dụ này, bạn sẽ đặt mã đó trực tiếp vào công cụ xây dựng // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3, sử dụng các tệp Python làm đầu vào. Để sử dụng // cmult.h
float cmult[int int_param, float float_param];
0, bạn bắt đầu bằng cách tạo một đối tượng $ python3 -m pip install invoke
16, đối tượng này cung cấp ba phương thức bạn cần$ python3 -m pip install invoke
4Khi bạn có FFI, bạn sẽ sử dụng
$ python3 -m pip install invoke
17 để tự động xử lý nội dung của tệp tiêu đề. Điều này tạo ra các hàm bao bọc để bạn sắp xếp dữ liệu từ Python$ python3 -m pip install invoke
5Đọc và xử lý tệp tiêu đề là bước đầu tiên. Sau đó, bạn cần sử dụng
$ python3 -m pip install invoke
18 để mô tả tệp nguồn mà // cmult.h
float cmult[int int_param, float float_param];
0 sẽ tạo$ python3 -m pip install invoke
6Đây là bảng phân tích các tham số bạn đang truyền vào
20 là tên cơ sở cho tệp nguồn sẽ được tạo trên hệ thống tệp của bạn.$ python3 -m pip install invoke
0 sẽ tạo ra một tệp// cmult.h float cmult[int int_param, float float_param];
22, biên dịch nó thành một tệp$ python3 -m pip install invoke
23 và liên kết nó với một tệp$ python3 -m pip install invoke
24 hoặc$ python3 -m pip install invoke
25$ python3 -m pip install invoke
26 là mã nguồn C tùy chỉnh sẽ được đưa vào nguồn được tạo trước khi nó được biên dịch. Ở đây, bạn chỉ bao gồm tệp$ python3 -m pip install invoke
27 mà bạn đang tạo liên kết, nhưng tệp này có thể được sử dụng cho một số tùy chỉnh thú vị$ python3 -m pip install invoke
28 cho trình liên kết biết tên của thư viện C có sẵn của bạn. Đây là danh sách, vì vậy bạn có thể chỉ định một số thư viện nếu cần$ python3 -m pip install invoke
29 là danh sách các thư mục cho trình liên kết biết nơi tìm danh sách thư viện ở trên$ python3 -m pip install invoke
30 là một tập hợp các tùy chọn tạo ra một đối tượng được chia sẻ, đối tượng này sẽ tìm trong đường dẫn hiện tại [$ python3 -m pip install invoke
31] để biết các thư viện khác mà nó cần tải$ python3 -m pip install invoke
Xây dựng các ràng buộc Python
Gọi
$ python3 -m pip install invoke
18 không xây dựng các liên kết Python. Nó chỉ thiết lập siêu dữ liệu để mô tả những gì sẽ được tạo. Để xây dựng các liên kết Python, bạn cần gọi ____13_______33$ python3 -m pip install invoke
7Điều này kết thúc mọi thứ bằng cách tạo tệp
$ python3 -m pip install invoke
22, tệp $ python3 -m pip install invoke
23 và thư viện dùng chung. Tác vụ // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3 mà bạn vừa thực hiện có thể được chạy trên dòng lệnh để xây dựng các liên kết Python$ python3 -m pip install invoke
8Bạn có các liên kết Python
// cmult.h
float cmult[int int_param, float float_param];
0 của mình, vì vậy đã đến lúc chạy mã nàyGọi chức năng của bạn
Sau tất cả công việc bạn đã thực hiện để định cấu hình và chạy trình biên dịch
// cmult.h
float cmult[int int_param, float float_param];
0, việc sử dụng các liên kết Python đã tạo trông giống như sử dụng bất kỳ mô-đun Python nào khác$ python3 -m pip install invoke
9Bạn nhập mô-đun mới, sau đó bạn có thể gọi trực tiếp ____13_______39. Để kiểm tra, hãy sử dụng tác vụ
$ python3 -m pip install invoke
40$ invoke build-cmult
==================================================
= Building C Library
* Complete
0Thao tác này sẽ chạy chương trình
$ python3 -m pip install invoke
41 của bạn, chương trình này sẽ kiểm tra các liên kết Python mới mà bạn đã tạo với // cmult.h
float cmult[int int_param, float float_param];
0. Điều đó hoàn thành phần viết và sử dụng các liên kết Python // cmult.h
float cmult[int int_param, float float_param];
0 của bạnLoại bỏ các quảng cáoĐiểm mạnh và điểm yếu
Có vẻ như
// cmult.h
float cmult[int int_param, float float_param];
2 yêu cầu ít thao tác hơn ví dụ // cmult.h
float cmult[int int_param, float float_param];
0 mà bạn vừa thấy. Mặc dù điều này đúng với trường hợp sử dụng này, nhưng // cmult.h
float cmult[int int_param, float float_param];
0 mở rộng quy mô cho các dự án lớn hơn tốt hơn nhiều so với // cmult.h
float cmult[int int_param, float float_param];
2 do tự động hóa phần lớn gói chức năng// cmult.h
float cmult[int int_param, float float_param];
0 cũng tạo ra trải nghiệm người dùng hoàn toàn khác. // cmult.h
float cmult[int int_param, float float_param];
2 cho phép bạn tải trực tiếp thư viện C có sẵn vào chương trình Python của bạn. Mặt khác, // cmult.h
float cmult[int int_param, float float_param];
0 tạo một mô-đun Python mới có thể được tải như các mô-đun Python khácNgoài ra, với phương pháp API ngoài luồng mà bạn đã sử dụng ở trên, thời gian phạt để tạo các ràng buộc Python được thực hiện một lần khi bạn xây dựng nó và không xảy ra mỗi khi bạn chạy mã của mình. Đối với các chương trình nhỏ, đây có thể không phải là vấn đề lớn, nhưng
// cmult.h
float cmult[int int_param, float float_param];
0 cũng mở rộng quy mô tốt hơn cho các dự án lớn hơn theo cách nàyGiống như
// cmult.h
float cmult[int int_param, float float_param];
2, sử dụng // cmult.h
float cmult[int int_param, float float_param];
0 chỉ cho phép bạn giao tiếp trực tiếp với các thư viện C. Các thư viện C++ yêu cầu rất nhiều công việc để sử dụng. Trong phần tiếp theo, bạn sẽ thấy một công cụ ràng buộc Python tập trung vào C++$ python3 -m pip install invoke
54
$ python3 -m pip install invoke
$ python3 -m pip install invoke
54 thực hiện một cách tiếp cận hoàn toàn khác để tạo các liên kết Python. Ngoài việc chuyển trọng tâm từ C sang C++, nó còn sử dụng C++ để chỉ định và xây dựng mô-đun, cho phép nó tận dụng lợi thế của các công cụ lập trình siêu dữ liệu trong C++. Giống như // cmult.h
float cmult[int int_param, float float_param];
0, các ràng buộc Python được tạo từ $ python3 -m pip install invoke
54 là một mô-đun Python đầy đủ có thể được nhập và sử dụng trực tiếp$ python3 -m pip install invoke
54 được mô phỏng theo thư viện $ python3 -m pip install invoke
59 và có giao diện tương tự. Tuy nhiên, nó hạn chế sử dụng C ++ 11 trở lên, cho phép nó đơn giản hóa và tăng tốc mọi thứ so với Boost, hỗ trợ mọi thứNó được cài đặt như thế nào
Phần Các bước đầu tiên của tài liệu
$ python3 -m pip install invoke
54 hướng dẫn bạn cách tải xuống và xây dựng các trường hợp thử nghiệm cho $ python3 -m pip install invoke
54. Mặc dù điều này dường như không bắt buộc, nhưng thực hiện qua các bước này sẽ đảm bảo bạn đã thiết lập các công cụ C++ và Python phù hợpGhi chú. Hầu hết các ví dụ cho
$ python3 -m pip install invoke
54 sử dụng $ python3 -m pip install invoke
63, đây là một công cụ tốt để xây dựng các dự án C và C++. Tuy nhiên, đối với bản trình diễn này, bạn sẽ tiếp tục sử dụng công cụ // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3, theo hướng dẫn trong phần tài liệuBạn sẽ muốn cài đặt công cụ này vào môi trường ảo của mình
$ invoke build-cmult
==================================================
= Building C Library
* Complete
1$ python3 -m pip install invoke
54 là một thư viện toàn tiêu đề, tương tự như phần lớn của Boost. Điều này cho phép // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
8 cài đặt nguồn C++ thực tế cho thư viện trực tiếp vào môi trường ảo của bạnGọi hàm
Trước khi đi sâu vào, xin lưu ý rằng bạn đang sử dụng một tệp nguồn C++ khác,
$ python3 -m pip install invoke
67, thay vì tệp C mà bạn đã sử dụng cho các ví dụ trước. Chức năng về cơ bản là giống nhau trong cả hai ngôn ngữViết các ràng buộc
Tương tự như
// cmult.h
float cmult[int int_param, float float_param];
0, bạn cần tạo một số mã để cho công cụ biết cách xây dựng các liên kết Python của bạn. Không giống như // cmult.h
float cmult[int int_param, float float_param];
0, mã này sẽ bằng C++ thay vì Python. May mắn thay, có một lượng mã tối thiểu được yêu cầu$ invoke build-cmult
==================================================
= Building C Library
* Complete
2Hãy cùng xem xét từng phần một, vì
$ python3 -m pip install invoke
54 gói gọn rất nhiều thông tin vào một vài dòngHai dòng đầu tiên bao gồm tệp
$ python3 -m pip install invoke
71 và tệp tiêu đề cho thư viện C++ của bạn, $ python3 -m pip install invoke
72. Sau đó, bạn có macro $ python3 -m pip install invoke
73. Điều này mở rộng thành một khối mã C++ được mô tả rõ ràng trong nguồn $ python3 -m pip install invoke
54Macro này tạo điểm vào sẽ được gọi khi trình thông dịch Python nhập mô-đun mở rộng. Tên mô-đun được đưa ra làm đối số đầu tiên và nó không được đặt trong dấu ngoặc kép. Đối số macro thứ hai xác định một biến loại
75 có thể được sử dụng để khởi tạo mô-đun. []$ python3 -m pip install invoke
Điều này có ý nghĩa gì đối với bạn, trong ví dụ này, bạn đang tạo một mô-đun có tên là
$ python3 -m pip install invoke
76 và phần còn lại của mã sẽ sử dụng $ python3 -m pip install invoke
77 làm tên của đối tượng $ python3 -m pip install invoke
75. Ở dòng tiếp theo, bên trong hàm C++ mà bạn đang xác định, bạn tạo một mô-đun cho. Mặc dù điều này là tùy chọn, nhưng thật tuyệt khi làm cho mô-đun của bạn giống Pythonic hơnCuối cùng, bạn có cuộc gọi
$ python3 -m pip install invoke
79. Điều này sẽ xác định một hàm được xuất bởi các liên kết Python mới của bạn, nghĩa là nó sẽ hiển thị từ Python. Trong ví dụ này, bạn đang truyền ba tham số
80 là tên đã xuất của hàm mà bạn sẽ sử dụng trong Python. Như ví dụ này cho thấy, nó không cần phải khớp với tên của hàm C++$ python3 -m pip install invoke
81 lấy địa chỉ của hàm được xuất$ python3 -m pip install invoke
82 là một chuỗi tài liệu tùy chọn cho chức năng$ python3 -m pip install invoke
Bây giờ bạn đã có mã cho các liên kết Python, hãy xem cách bạn có thể xây dựng mã này thành một mô-đun Python
Xây dựng các ràng buộc Python
Công cụ bạn sử dụng để xây dựng các ràng buộc Python trong
$ python3 -m pip install invoke
54 chính là trình biên dịch C++. Bạn có thể cần sửa đổi các giá trị mặc định cho trình biên dịch và hệ điều hành của mìnhĐể bắt đầu, bạn phải xây dựng thư viện C++ mà bạn đang tạo ràng buộc. Đối với một ví dụ nhỏ này, bạn có thể xây dựng thư viện
$ python3 -m pip install invoke
84 trực tiếp vào thư viện liên kết Python. Tuy nhiên, đối với hầu hết các ví dụ trong thế giới thực, bạn sẽ có một thư viện sẵn có mà bạn muốn đóng gói, vì vậy bạn sẽ xây dựng thư viện $ python3 -m pip install invoke
84 riêng biệt. Bản dựng là lời gọi tiêu chuẩn tới trình biên dịch để xây dựng thư viện dùng chung$ invoke build-cmult
==================================================
= Building C Library
* Complete
3Chạy cái này với
$ python3 -m pip install invoke
86 tạo ra $ python3 -m pip install invoke
87$ invoke build-cmult
==================================================
= Building C Library
* Complete
4Mặt khác, bản dựng cho các liên kết Python yêu cầu một số chi tiết đặc biệt
$ invoke build-cmult
==================================================
= Building C Library
* Complete
5Hãy đi qua từng dòng này. Dòng 3 chứa các cờ trình biên dịch C++ khá chuẩn cho biết một số chi tiết, bao gồm việc bạn muốn tất cả các cảnh báo bị bắt và coi là lỗi, rằng bạn muốn có một thư viện dùng chung và rằng bạn đang sử dụng C++11
Dòng 4 là bước đầu tiên của phép thuật. Nó gọi mô-đun
$ python3 -m pip install invoke
88 để yêu cầu nó tạo ra các đường dẫn $ python3 -m pip install invoke
89 thích hợp cho $ python3 -m pip install invoke
54. Bạn có thể chạy lệnh này trực tiếp trên bàn điều khiển để xem những gì nó làm$ invoke build-cmult
==================================================
= Building C Library
* Complete
6Đầu ra của bạn phải tương tự nhưng hiển thị các đường dẫn khác nhau
Trong dòng 5 của cuộc gọi biên dịch của bạn, bạn có thể thấy rằng bạn cũng đang thêm đường dẫn đến nhà phát triển Python
$ python3 -m pip install invoke
91. Mặc dù chúng tôi khuyên bạn không nên liên kết với chính thư viện Python, nguồn cần một số mã từ $ python3 -m pip install invoke
92 để phát huy tác dụng kỳ diệu của nó. May mắn thay, mã mà nó sử dụng khá ổn định trên các phiên bản PythonDòng 5 cũng sử dụng
$ python3 -m pip install invoke
93 để thêm thư mục hiện tại vào danh sách các đường dẫn $ python3 -m pip install invoke
89. Điều này cho phép giải quyết dòng $ python3 -m pip install invoke
95 trong mã bao bọc của bạnDòng 6 chỉ định tên tệp nguồn của bạn, đó là
$ python3 -m pip install invoke
96. Sau đó, trên dòng 7, bạn thấy một số ma thuật xây dựng khác đang xảy ra. Dòng này chỉ định tên của tệp đầu ra. Python có một số ý tưởng cụ thể về đặt tên mô-đun, bao gồm phiên bản Python, kiến trúc máy và các chi tiết khác. Python cũng cung cấp một công cụ để trợ giúp việc này có tên là $ python3 -m pip install invoke
97$ invoke build-cmult
==================================================
= Building C Library
* Complete
7Bạn có thể cần sửa đổi lệnh nếu đang sử dụng phiên bản Python khác. Kết quả của bạn có thể sẽ thay đổi nếu bạn đang sử dụng một phiên bản Python khác hoặc đang sử dụng một hệ điều hành khác
Dòng cuối cùng của lệnh xây dựng của bạn, dòng 8, trỏ trình liên kết vào thư viện
$ python3 -m pip install invoke
98 mà bạn đã xây dựng trước đó. Phần $ python3 -m pip install invoke
99 yêu cầu trình liên kết thêm thông tin vào thư viện dùng chung để giúp hệ điều hành tìm thấy $ python3 -m pip install invoke
98 khi chạy. Cuối cùng, bạn sẽ nhận thấy rằng chuỗi này được định dạng bằng $ invoke build-cmult
==================================================
= Building C Library
* Complete
01 và $ invoke build-cmult
==================================================
= Building C Library
* Complete
02. Bạn sẽ sử dụng lại chức năng này khi xây dựng mô-đun liên kết Python của mình với $ invoke build-cmult
==================================================
= Building C Library
* Complete
03 trong phần tiếp theoChạy lệnh này để xây dựng các ràng buộc của bạn
$ invoke build-cmult
==================================================
= Building C Library
* Complete
8Đó là nó. Bạn đã xây dựng các liên kết Python của mình với
$ python3 -m pip install invoke
54. Đã đến lúc kiểm tra nóGọi chức năng của bạn
Tương tự như ví dụ
// cmult.h
float cmult[int int_param, float float_param];
0 ở trên, khi bạn đã hoàn thành công việc nặng nhọc là tạo các liên kết Python, việc gọi hàm của bạn trông giống như mã Python bình thường$ invoke build-cmult
==================================================
= Building C Library
* Complete
9Vì bạn đã sử dụng
$ python3 -m pip install invoke
76 làm tên mô-đun của mình trong macro $ python3 -m pip install invoke
73, nên đó là tên bạn nhập. Trong cuộc gọi $ python3 -m pip install invoke
79, bạn đã yêu cầu $ python3 -m pip install invoke
54 xuất hàm $ python3 -m pip install invoke
84 dưới dạng $ python3 -m pip install invoke
80, vì vậy đó là những gì bạn sử dụng để gọi nó từ PythonBạn cũng có thể kiểm tra nó với
// cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3$ invoke --list
Available tasks:
all Build and run all tests
build-cffi Build the CFFI Python bindings
build-cmult Build the shared library for the sample C code
build-cppmult Build the shared library for the sample C++ code
build-cython Build the cython extension module
build-pybind11 Build the pybind11 wrapper library
clean Remove any built objects
test-cffi Run the script to test CFFI
test-ctypes Run the script to test ctypes
test-cython Run the script to test Cython
test-pybind11 Run the script to test PyBind11
0Đó là những gì
$ python3 -m pip install invoke
54 trông giống như. Tiếp theo, bạn sẽ thấy khi nào và tại sao $ python3 -m pip install invoke
54 là công cụ phù hợp cho công việcLoại bỏ các quảng cáoĐiểm mạnh và điểm yếu
$ python3 -m pip install invoke
54 tập trung vào C++ thay vì C, điều này làm cho nó khác với // cmult.h
float cmult[int int_param, float float_param];
2 và // cmult.h
float cmult[int int_param, float float_param];
0. Nó có một số tính năng khiến nó trở nên khá hấp dẫn đối với các thư viện C++- Nó hỗ trợ các lớp
- Nó xử lý phân lớp đa hình
- Nó cho phép bạn thêm các thuộc tính động vào các đối tượng từ Python và nhiều công cụ khác, điều này khá khó thực hiện với các công cụ dựa trên C mà bạn đã kiểm tra
Như đã nói, bạn cần thực hiện một chút thiết lập và cấu hình để thiết lập và chạy
$ python3 -m pip install invoke
54. Việc cài đặt và xây dựng chính xác có thể hơi phức tạp, nhưng một khi đã hoàn tất, nó có vẻ khá vững chắc. Ngoài ra, $ python3 -m pip install invoke
54 yêu cầu bạn sử dụng ít nhất C++ 11 hoặc mới hơn. Đây không phải là một hạn chế lớn đối với hầu hết các dự án, nhưng nó có thể là một sự cân nhắc cho bạnCuối cùng, mã bổ sung bạn cần viết để tạo các liên kết Python nằm trong C++ chứ không phải Python. Đây có thể là vấn đề hoặc không đối với bạn, nhưng nó khác với các công cụ khác mà bạn đã xem tại đây. Trong phần tiếp theo, bạn sẽ chuyển sang
$ invoke build-cmult
==================================================
= Building C Library
* Complete
03, cách tiếp cận vấn đề này hoàn toàn khác$ invoke build-cmult
==================================================
= Building C Library
* Complete
03
$ invoke build-cmult
==================================================
= Building C Library
* Complete
Cách tiếp cận
$ invoke build-cmult
==================================================
= Building C Library
* Complete
03 để tạo các liên kết Python sử dụng ngôn ngữ giống Python để xác định các liên kết và sau đó tạo mã C hoặc C++ có thể được biên dịch vào mô-đun. Có một số phương pháp để xây dựng các liên kết Python với $ invoke build-cmult
==================================================
= Building C Library
* Complete
03. Cách phổ biến nhất là sử dụng $ invoke build-cmult
==================================================
= Building C Library
* Complete
24 từ $ invoke build-cmult
==================================================
= Building C Library
* Complete
25. Đối với ví dụ này, bạn sẽ sử dụng công cụ // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3, công cụ này sẽ cho phép bạn chơi với các lệnh chính xác được chạyNó được cài đặt như thế nào
$ invoke build-cmult
==================================================
= Building C Library
* Complete
03 là một mô-đun Python có thể được cài đặt vào môi trường ảo của bạn từ PyPI$ invoke --list
Available tasks:
all Build and run all tests
build-cffi Build the CFFI Python bindings
build-cmult Build the shared library for the sample C code
build-cppmult Build the shared library for the sample C++ code
build-cython Build the cython extension module
build-pybind11 Build the pybind11 wrapper library
clean Remove any built objects
test-cffi Run the script to test CFFI
test-ctypes Run the script to test ctypes
test-cython Run the script to test Cython
test-pybind11 Run the script to test PyBind11
1Một lần nữa, nếu bạn đã cài đặt tệp
$ python3 -m pip install invoke
05 vào môi trường ảo của mình, thì tệp này sẽ ở đó rồi. Bạn có thể lấy một bản sao của $ python3 -m pip install invoke
05 bằng cách nhấp vào liên kết bên dướiNhận mã mẫu. Nhấp vào đây để lấy mã mẫu mà bạn sẽ sử dụng để tìm hiểu về Python Bindings trong hướng dẫn này
Điều đó sẽ giúp bạn sẵn sàng làm việc với
$ invoke build-cmult
==================================================
= Building C Library
* Complete
03Gọi hàm
Để xây dựng các ràng buộc Python của bạn với
$ invoke build-cmult
==================================================
= Building C Library
* Complete
03, bạn sẽ làm theo các bước tương tự như những bước bạn đã sử dụng cho // cmult.h
float cmult[int int_param, float float_param];
0 và $ python3 -m pip install invoke
54. Bạn sẽ viết các liên kết, xây dựng chúng và sau đó chạy mã Python để gọi chúng. $ invoke build-cmult
==================================================
= Building C Library
* Complete
03 có thể hỗ trợ cả C và C++. Đối với ví dụ này, bạn sẽ sử dụng thư viện $ python3 -m pip install invoke
84 mà bạn đã sử dụng cho ví dụ $ python3 -m pip install invoke
54 ở trênViết các ràng buộc
Hình thức phổ biến nhất để khai báo một mô-đun trong
$ invoke build-cmult
==================================================
= Building C Library
* Complete
03 là sử dụng tệp $ invoke build-cmult
==================================================
= Building C Library
* Complete
38$ invoke --list
Available tasks:
all Build and run all tests
build-cffi Build the CFFI Python bindings
build-cmult Build the shared library for the sample C code
build-cppmult Build the shared library for the sample C++ code
build-cython Build the cython extension module
build-pybind11 Build the pybind11 wrapper library
clean Remove any built objects
test-cffi Run the script to test CFFI
test-ctypes Run the script to test ctypes
test-cython Run the script to test Cython
test-pybind11 Run the script to test PyBind11
2Có hai phần ở đây
- Dòng 3 và 4 cho biết
03 rằng bạn đang sử dụng$ invoke build-cmult ================================================== = Building C Library * Complete
40 từ$ invoke build-cmult ================================================== = Building C Library * Complete
72$ python3 -m pip install invoke
- Dòng 6 và 7 tạo hàm bao bọc,
42, để gọi$ invoke build-cmult ================================================== = Building C Library * Complete
40$ invoke build-cmult ================================================== = Building C Library * Complete
Ngôn ngữ được sử dụng ở đây là sự kết hợp đặc biệt giữa C, C++ và Python. Tuy nhiên, nó sẽ trông khá quen thuộc với các nhà phát triển Python, vì mục tiêu là làm cho quá trình này dễ dàng hơn
Phần đầu tiên với
$ invoke build-cmult
==================================================
= Building C Library
* Complete
44 nói với $ invoke build-cmult
==================================================
= Building C Library
* Complete
03 rằng các khai báo hàm bên dưới cũng được tìm thấy trong tệp $ python3 -m pip install invoke
72. Điều này hữu ích để đảm bảo rằng các ràng buộc Python của bạn được xây dựng dựa trên các khai báo giống như mã C++ của bạn. Phần thứ hai trông giống như một hàm Python thông thường—bởi vì nó là. Phần này tạo một hàm Python có quyền truy cập vào hàm C++ $ python3 -m pip install invoke
84Bây giờ bạn đã xác định được các liên kết Python, đã đến lúc xây dựng chúng
Xây dựng các ràng buộc Python
Quy trình xây dựng cho
$ invoke build-cmult
==================================================
= Building C Library
* Complete
03 có những điểm tương đồng với quy trình bạn đã sử dụng cho $ python3 -m pip install invoke
54. Trước tiên, bạn chạy $ invoke build-cmult
==================================================
= Building C Library
* Complete
03 trên tệp $ invoke build-cmult
==================================================
= Building C Library
* Complete
38 để tạo tệp $ invoke build-cmult
==================================================
= Building C Library
* Complete
52. Khi bạn đã hoàn thành việc này, bạn biên dịch nó với cùng chức năng mà bạn đã sử dụng cho $ python3 -m pip install invoke
54$ invoke --list
Available tasks:
all Build and run all tests
build-cffi Build the CFFI Python bindings
build-cmult Build the shared library for the sample C code
build-cppmult Build the shared library for the sample C++ code
build-cython Build the cython extension module
build-pybind11 Build the pybind11 wrapper library
clean Remove any built objects
test-cffi Run the script to test CFFI
test-ctypes Run the script to test ctypes
test-cython Run the script to test Cython
test-pybind11 Run the script to test PyBind11
3Bạn bắt đầu bằng cách chạy
$ invoke build-cmult
==================================================
= Building C Library
* Complete
54 trên tệp $ invoke build-cmult
==================================================
= Building C Library
* Complete
38 của mình. Có một vài tùy chọn bạn sử dụng trên lệnh này
56 yêu cầu trình biên dịch tạo tệp C++ thay vì tệp C$ invoke build-cmult ================================================== = Building C Library * Complete
57 chuyển đổi$ invoke build-cmult ================================================== = Building C Library * Complete
03 để tạo cú pháp Python 3 thay vì Python 2$ invoke build-cmult ================================================== = Building C Library * Complete
59 chỉ định tên của tệp sẽ tạo$ invoke build-cmult ================================================== = Building C Library * Complete
Khi tệp C++ được tạo, bạn sử dụng trình biên dịch C++ để tạo các ràng buộc Python, giống như bạn đã làm cho
$ python3 -m pip install invoke
54. Lưu ý rằng lời gọi để tạo thêm các đường dẫn $ python3 -m pip install invoke
89 bằng cách sử dụng công cụ $ python3 -m pip install invoke
88 vẫn nằm trong chức năng đó. Nó sẽ không ảnh hưởng gì ở đây, vì nguồn của bạn sẽ không cần những thứ đóChạy tác vụ này trong
// cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3 tạo ra kết quả này$ invoke --list
Available tasks:
all Build and run all tests
build-cffi Build the CFFI Python bindings
build-cmult Build the shared library for the sample C code
build-cppmult Build the shared library for the sample C++ code
build-cython Build the cython extension module
build-pybind11 Build the pybind11 wrapper library
clean Remove any built objects
test-cffi Run the script to test CFFI
test-ctypes Run the script to test ctypes
test-cython Run the script to test Cython
test-pybind11 Run the script to test PyBind11
4Bạn có thể thấy rằng nó xây dựng thư viện
$ python3 -m pip install invoke
84 và sau đó xây dựng mô-đun $ invoke build-cmult
==================================================
= Building C Library
* Complete
54 để bọc nó. Bây giờ bạn có các liên kết Python $ invoke build-cmult
==================================================
= Building C Library
* Complete
03. [Thử nói nhanh đi…] Đã đến lúc thử nghiệmGọi chức năng của bạn
Mã Python để gọi các liên kết Python mới của bạn khá giống với mã bạn đã sử dụng để kiểm tra các mô-đun khác
$ invoke --list
Available tasks:
all Build and run all tests
build-cffi Build the CFFI Python bindings
build-cmult Build the shared library for the sample C code
build-cppmult Build the shared library for the sample C++ code
build-cython Build the cython extension module
build-pybind11 Build the pybind11 wrapper library
clean Remove any built objects
test-cffi Run the script to test CFFI
test-ctypes Run the script to test ctypes
test-cython Run the script to test Cython
test-pybind11 Run the script to test PyBind11
5Dòng 2 nhập mô-đun ràng buộc Python mới của bạn và bạn gọi
$ invoke build-cmult
==================================================
= Building C Library
* Complete
42 trên dòng 7. Hãy nhớ rằng tệp $ invoke build-cmult
==================================================
= Building C Library
* Complete
38 đã cung cấp trình bao bọc Python xung quanh $ invoke build-cmult
==================================================
= Building C Library
* Complete
40 và đổi tên nó thành $ invoke build-cmult
==================================================
= Building C Library
* Complete
70. Sử dụng gọi để chạy thử nghiệm của bạn tạo ra như sau$ invoke --list
Available tasks:
all Build and run all tests
build-cffi Build the CFFI Python bindings
build-cmult Build the shared library for the sample C code
build-cppmult Build the shared library for the sample C++ code
build-cython Build the cython extension module
build-pybind11 Build the pybind11 wrapper library
clean Remove any built objects
test-cffi Run the script to test CFFI
test-ctypes Run the script to test ctypes
test-cython Run the script to test Cython
test-pybind11 Run the script to test PyBind11
6Bạn nhận được kết quả tương tự như trước đây
Loại bỏ các quảng cáoĐiểm mạnh và điểm yếu
$ invoke build-cmult
==================================================
= Building C Library
* Complete
03 là một công cụ tương đối phức tạp có thể cung cấp cho bạn mức độ kiểm soát sâu sắc khi tạo các liên kết Python cho C hoặc C++. Mặc dù bạn không đề cập sâu ở đây, nhưng nó cung cấp một phương pháp Python-esque để viết mã điều khiển GIL theo cách thủ công, có thể tăng tốc đáng kể một số loại sự cốTuy nhiên, ngôn ngữ Python-esque đó không hoàn toàn là Python, do đó, có một chút đường cong học tập khi bạn bắt đầu tăng tốc trong việc tìm ra phần nào của C và Python phù hợp với vị trí nào.
Giải pháp khác
Trong khi nghiên cứu hướng dẫn này, tôi đã tìm thấy một số công cụ và tùy chọn khác nhau để tạo các liên kết Python. Mặc dù tôi giới hạn tổng quan này ở một số tùy chọn phổ biến hơn, nhưng có một số công cụ khác mà tôi tình cờ tìm thấy. Danh sách dưới đây không đầy đủ. Nó chỉ đơn thuần là lấy mẫu các khả năng khác nếu một trong những công cụ trên không phù hợp với dự án của bạn
$ invoke build-cmult
==================================================
= Building C Library
* Complete
72
$ invoke build-cmult
==================================================
= Building C Library
* Complete
tạo các ràng buộc Python cho C hoặc C++ và được viết bằng Python. Nó được nhắm mục tiêu tạo mã C hoặc C ++ có thể đọc được, điều này sẽ đơn giản hóa các vấn đề gỡ lỗi. Không rõ liệu điều này đã được cập nhật gần đây chưa, vì tài liệu liệt kê Python 3. 4 là phiên bản thử nghiệm mới nhất. Đã có những bản phát hành hàng năm trong vài năm qua, tuy nhiên
$ invoke build-cmult
==================================================
= Building C Library
* Complete
74
$ invoke build-cmult
==================================================
= Building C Library
* Complete
$ invoke build-cmult
==================================================
= Building C Library
* Complete
74 có giao diện tương tự như $ python3 -m pip install invoke
54 mà bạn đã thấy ở trên. Đó không phải là sự trùng hợp ngẫu nhiên, vì $ python3 -m pip install invoke
54 dựa trên thư viện này. $ invoke build-cmult
==================================================
= Building C Library
* Complete
74 được viết bằng C++ đầy đủ và hỗ trợ hầu hết, nếu không muốn nói là tất cả, các phiên bản C++ trên hầu hết các nền tảng. Ngược lại, $ python3 -m pip install invoke
54 tự giới hạn trong C++ hiện đại$ invoke build-cmult
==================================================
= Building C Library
* Complete
80
$ invoke build-cmult
==================================================
= Building C Library
* Complete
$ invoke build-cmult
==================================================
= Building C Library
* Complete
80 là bộ công cụ để tạo các liên kết Python được phát triển cho dự án PyQt. Nó cũng được dự án wxPython sử dụng để tạo các ràng buộc của chúng. Nó có một công cụ tạo mã và một mô-đun Python bổ sung cung cấp các chức năng hỗ trợ cho mã được tạo$ invoke build-cmult
==================================================
= Building C Library
* Complete
82
$ invoke build-cmult
==================================================
= Building C Library
* Complete
$ invoke build-cmult
==================================================
= Building C Library
* Complete
83 là một công cụ thú vị có mục tiêu thiết kế hơi khác so với những gì bạn đã thấy cho đến nay. Theo lời của tác giả gói“Ý tưởng ban đầu đằng sau cppyy [từ năm 2001] là cho phép các lập trình viên Python sống trong thế giới C++ truy cập vào các gói C++ đó mà không cần phải chạm trực tiếp vào C++ [hoặc đợi các nhà phát triển C++ xuất hiện và cung cấp các ràng buộc]. " [Nguồn]
$ invoke build-cmult
==================================================
= Building C Library
* Complete
84
$ invoke build-cmult
==================================================
= Building C Library
* Complete
$ invoke build-cmult
==================================================
= Building C Library
* Complete
84 là một công cụ để tạo các liên kết Python được phát triển cho dự án PySide được liên kết với dự án Qt. Mặc dù nó được thiết kế như một công cụ cho dự án đó, nhưng tài liệu chỉ ra rằng nó không dành riêng cho Qt- hay PySide và có thể sử dụng được cho các dự án khác$ invoke build-cmult
==================================================
= Building C Library
* Complete
86
$ invoke build-cmult
==================================================
= Building C Library
* Complete
$ invoke build-cmult
==================================================
= Building C Library
* Complete
86 là một công cụ khác với bất kỳ công cụ nào khác được liệt kê ở đây. Nó là một công cụ chung được sử dụng để tạo các liên kết với các chương trình C và C++, không chỉ Python. Khả năng tạo ràng buộc cho các ngôn ngữ khác nhau này có thể khá hữu ích trong một số dự án. Tất nhiên, nó đi kèm với một chi phí liên quan đến sự phức tạp.Phần kết luận
chúc mừng. Bây giờ bạn đã có tổng quan về một số tùy chọn khác nhau để tạo các liên kết Python. Bạn đã học về sắp xếp dữ liệu và các vấn đề bạn cần xem xét khi tạo liên kết. Bạn đã thấy những gì cần thiết để có thể gọi một hàm C hoặc C++ từ Python bằng các công cụ sau
2// cmult.h float cmult[int int_param, float float_param];
0// cmult.h float cmult[int int_param, float float_param];
54$ python3 -m pip install invoke
03$ invoke build-cmult ================================================== = Building C Library * Complete
Bây giờ bạn đã biết rằng, trong khi
// cmult.h
float cmult[int int_param, float float_param];
2 cho phép bạn tải trực tiếp tệp DLL hoặc thư viện dùng chung, ba công cụ còn lại thực hiện thêm một bước, nhưng vẫn tạo ra một mô-đun Python đầy đủ. Như một phần thưởng, bạn cũng đã chơi một chút với công cụ // cmult.c
float cmult[int int_param, float float_param] {
float return_value = int_param * float_param;
printf[" In cmult : int: %d float %.1f returning %.1f\n", int_param,
float_param, return_value];
return return_value;
}
3 để chạy các tác vụ dòng lệnh từ Python. Bạn có thể lấy tất cả mã bạn đã thấy trong hướng dẫn này bằng cách nhấp vào liên kết bên dướiNhận mã mẫu. Nhấp vào đây để lấy mã mẫu mà bạn sẽ sử dụng để tìm hiểu về Python Bindings trong hướng dẫn này
Bây giờ hãy chọn công cụ yêu thích của bạn và bắt đầu xây dựng các liên kết Python đó. Đặc biệt cảm ơn Loic Domaigne đã xem xét kỹ thuật bổ sung cho hướng dẫn này
Đá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ề Jim Anderson
Jim đã lập trình trong một thời gian dài bằng nhiều ngôn ngữ. Anh ấy đã làm việc trên các hệ thống nhúng, xây dựng các hệ thống xây dựng phân tán, quản lý nhà cung cấp nước ngoài và tham gia rất nhiều cuộc họp
» Thông tin thêm về JimMỗ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
Geir Arne
Jaya
Joanna
Mike
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