2010-10-17 22 views
8

Tôi đang cố viết một trình cắm phần mềm nhúng Python. Trên Windows, trình cắm thêm về kỹ thuật là một DLL (điều này có thể có liên quan). Số Python Windows FAQ cho biết:Nhúng Python trên Windows: tại sao nó phải là một DLL?

1.Do không hãy tạo Python trực tiếp vào tệp .exe của bạn. Trên Windows, Python phải là một DLL để xử lý các mô-đun nhập khẩu là bản thân DLL. (Đây là chìa khóa đầu tiên không có giấy tờ thực tế.) Thay vào đó, liên kết đến pythonNN.dll; nó thường được cài đặt trong C: \ Windows \ System. NN là phiên bản Python, một số như “23” cho Python 2.3.

Câu hỏi của tôi là tại sao chính xác Python phải là một DLL? Nếu, như trong trường hợp của tôi, ứng dụng máy chủ không phải là .exe, mà còn là một DLL, tôi có thể xây dựng Python vào nó không? Hoặc, có lẽ, lưu ý này có nghĩa là các tiện ích mở rộng của bên thứ ba dựa trên pythonN.N.dll để có mặt và các DLL khác sẽ không làm gì? Giả sử rằng tôi muốn thực sự muốn có một DLL duy nhất, tôi nên làm gì?

Tôi thấy có tệp dynload_win.c, có vẻ như là mô-đun để nhập các tiện ích mở rộng C trên Windows và, theo như tôi thấy, tệp sẽ quét tệp tiện ích mở rộng để tìm kiếm nhập pythonX.X.dll nào; nhưng tôi không có kinh nghiệm với Windows và tôi không hoàn toàn hiểu tất cả các mã ở đó.

Trả lời

4

Bạn cần phải liên kết đến pythonXY.dll như một DLL, thay vì liên kết mã có liên quan trực tiếp vào thực thi của bạn, bởi vì nếu không thời gian chạy Python không thể tải DLL khác (các module mở rộng nó dựa trên). Nếu bạn thực hiện DLL của riêng bạn, bạn về mặt lý thuyết có thể liên kết tất cả các mã Python trong đó DLL trực tiếp, vì nó không kết thúc trong thực thi nhưng vẫn còn trong một DLL. Bạn sẽ phải cẩn thận để làm các liên kết một cách chính xác, tuy nhiên, như khá nhiều không có công cụ tiêu chuẩn (như distutils) sẽ làm điều này cho bạn.

Tuy nhiên, bất kể cách bạn nhúng Python, bạn không thể thực hiện với chỉ DLL, cũng như bạn không thể thực hiện chỉ với bất kỳ DLL nào. ABI thay đổi giữa các phiên bản Python, vì vậy nếu bạn biên dịch mã của mình dựa trên Python 2.6, bạn cần python26.dll; bạn không thể sử dụng python25.dll hoặc python27.dll. Và Python không chỉ là một DLL; nó cũng cần thư viện chuẩn của nó, bao gồm các mô-đun mở rộng (là bản thân các DLL, mặc dù chúng có phần mở rộng là .pyd.) Mã trong số dynload_win.c mà bạn gặp phải là để tải những tệp DLL đó và không liên quan đến việc tải pythonXY.dll.

Tóm lại, để nhúng Python vào plugin của bạn, bạn cần phải gửi Python bằng plugin hoặc yêu cầu phiên bản Python phù hợp đã được cài đặt.

+0

Nếu tôi biên dịch các phần mở rộng thư viện chuẩn và liên kết chúng với DLL của tôi (sẽ được tạo bởi 'foo' và' bar' và tất cả các đối tượng thường đi vào 'pythonNN.dll' như tôi thấy trong' dự án pythoncore')? Trong trường hợp của tôi, OK có các phiên bản đặc biệt của thư viện chuẩn hoặc tiện ích mở rộng của bên thứ ba. –

+0

Sau đó, bạn vẫn cần tất cả phần còn lại của thư viện chuẩn (tất cả các tệp .py, và các tệp .pyc và .pyo thường.) Chúng cũng là phiên bản Python cụ thể. Bạn có thể nén chúng lên nhưng bạn không thể tránh chúng. –

+0

Vì vậy, về cơ bản, không có cách nào nhúng python trong ứng dụng của bạn mà không bó nó với một dll python? – viraj

0

Python cần phải là một dll (có tên chuẩn) sao cho ứng dụng của bạn và plugin có thể sử dụng cùng một phiên bản của python.

Plugin dlls dự kiến ​​sẽ tải (và sử dụng python từ) python26.dll (hoặc bất kỳ phiên bản nào) - nếu python của bạn được nhúng tĩnh trong exe, thì hai cá thể khác nhau của thư viện python sẽ là quản lý các cấu trúc dữ liệu giống nhau.

Nếu thư viện python không sử dụng biến tĩnh nào cả, và cài đặt biên dịch là chính xác điều này không phải là vấn đề. Tuy nhiên, nói chung nó an toàn hơn nhiều để chỉ đơn giản là đảm bảo rằng chỉ có một thể hiện của trình thông dịch python đang được sử dụng.

1

Trên * nix, tất cả các đối tượng được chia sẻ trong một quy trình, bao gồm cả tệp thực thi, đóng góp tên đã xuất của chúng vào một nhóm chung; bất kỳ đối tượng được chia sẻ nào sau đó có thể kéo bất kỳ tên nào từ nhóm và sử dụng chúng theo ý muốn. Điều này cho phép, ví dụ: cStringIO.so để kéo các hàm thư viện Python có liên quan từ tệp thực thi chính khi thư viện Python được liên kết tĩnh.

Trên Windows, mỗi đối tượng được chia sẻ có riêng biệt độc lập tên nhóm mà nó có thể sử dụng. Điều này có nghĩa là nó phải đọc các đối tượng chia sẻ có liên quan khác nhau mà nó cần các chức năng từ đó. Vì nó là rất nhiều công việc để có được tất cả các tên từ thực thi chính, các hàm Python được tách ra thành DLL riêng của chúng.

1

(Xin lỗi, tôi đã làm một điều ngu ngốc, trước tiên tôi đã viết câu hỏi, và sau đó đăng ký, và bây giờ tôi không thể thay đổi hoặc nhận xét về câu trả lời, vì động cơ của StackOverflow không nghĩ rằng tôi là tác giả. thậm chí đúng cảm ơn những người đã trả lời :(Vì vậy, đây thực sự là một bản cập nhật cho câu hỏi và nhận xét.)

Cảm ơn lời khuyên, nó rất có giá trị.Tuy nhiên tôi hiểu rằng tôi có thể liên kết Python tĩnh vào một DLL tùy chỉnh, miễn là tôi biên dịch các phần mở rộng tự động nạp khác và liên kết chúng với cùng một DLL. (Tôi biết rằng tôi cũng cần gửi thư viện chuẩn), kế hoạch của tôi là chắp thêm một tệp nén vào tệp DLL. , Tôi thậm chí sẽ có thể nhập các mô-đun Python thuần túy từ nó.)

Tôi cũng tìm thấy một địa điểm thú vị ở dynload_win.c. (Tôi hiểu nó tải các phần mở rộng động sử dụng Python C API, ví dụ như _ctypes.) Theo tôi có thể thấy nó không chỉ cho biểu tượng init_ctypes hoặc bất kỳ tên mở rộng nào, mà còn quét bảng nhập tệp của .pyd tìm kiếm (regex) python\d+\. và sau đó so sánh biểu tượng tìm thấy với chuỗi pythonNN. đã biết để đảm bảo tiện ích được biên dịch cho phiên bản Python này. Nếu bảng nhập khẩu không có biểu tượng như vậy hoặc nó chỉ một phiên bản khác, nó sẽ gây ra lỗi.

Đối với tôi nó có nghĩa là:

  • Nếu tôi liên kết một phần mở rộng chống lại pythonNN.dll và cố gắng để tải nó từ DLL tùy chỉnh của tôi bao gồm một Python liên kết tĩnh, nó sẽ vượt qua kiểm tra, nhưng - tốt, ở đây Tôi không chắc chắn: nó sẽ thất bại vì không có pythonNN.dll (tức là ngay cả trước khi đến kiểm tra) hoặc nó sẽ vui vẻ tải các biểu tượng?
  • Và nếu tôi liên kết nó chống lại DLL tùy chỉnh của tôi, nó sẽ tìm thấy biểu tượng, nhưng sẽ không vượt qua kiểm tra :)

Tôi đoán tôi có thể viết lại tác phẩm này cho phù hợp với nhu cầu của tôi ... Có bất kỳ những nơi khác, tôi tự hỏi.

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