2010-06-05 30 views
19

Tôi có một mô-đun Python, wrapper.py, kết thúc tốt đẹp một DLL C. DLL nằm trong cùng thư mục với module. Do đó, tôi sử dụng mã sau để tải mã:Python ctypes: tải DLL từ một đường dẫn tương đối

myDll = ctypes.CDLL("MyCDLL.dll") 

Điều này hoạt động nếu tôi thực hiện wrapper.py từ thư mục riêng của nó. Nếu, tuy nhiên, tôi chạy nó từ nơi khác, nó không thành công. Đó là bởi vì ctypes tính toán đường dẫn tương đối so với thư mục làm việc hiện tại.

Câu hỏi của tôi là, có cách nào để tôi có thể chỉ định đường dẫn của DLL liên quan đến trình bao bọc thay vì thư mục làm việc hiện tại không? Điều đó sẽ cho phép tôi gửi cả hai lại với nhau và cho phép người dùng chạy/nhập trình bao bọc từ bất kỳ đâu.

+1

Tôi sử dụng cách tiếp cận trong [câu trả lời đã chọn] (http://stackoverflow.com/a/2980501/1020470) nhưng trong một trường hợp tôi có dll đã nhập một xuất từ ​​một dll khác và nó sẽ không tải . Giải pháp là nạp các dll khác trước, EG: '_DIRNAME = os.path.dirname (__ file__); required_dll = ctypes.cdll.LoadLibrary (os.path.join (_DIRNAME, required.dll)); main_dll = ctypes.cdll.LoadLibrary (os.path.join (_DIRNAME, main.dll)) 'voila hoạt động! –

Trả lời

20

Bạn có thể sử dụng os.path.dirname(__file__) để lấy thư mục chứa tệp nguồn Python.

+0

Cảm ơn bạn rất nhiều. Đó chính xác là những gì tôi đang tìm kiếm. –

+0

Đường dẫn tương đối như thế này hoạt động tốt, không cần phải có 'os.path.abspath()' hoặc thêm đường dẫn này vào '$ PATH' ('% PATH% '). Một báo trước, nếu dll của bạn yêu cầu một dll, sau đó bạn sẽ phải tải đó quá, trước khi bạn tải này, xem bình luận của tôi theo câu hỏi của OP. –

6

Tôi luôn thêm thư mục chứa DLL của tôi vào đường dẫn. Điều đó hoạt động:

os.environ['PATH'] = os.path.dirname(__file__) + ';' + os.environ['PATH'] 
windll.LoadLibrary('mydll.dll') 

Lưu ý rằng nếu bạn sử dụng py2exe, điều này không hoạt động (vì __file__ chưa được đặt). Trong trường hợp đó, bạn cần phải dựa vào các sys.executable thuộc tính (hướng dẫn đầy đủ tại http://www.py2exe.org/index.cgi/WhereAmI)

+0

['os.pathsep'] (http://docs.python.org/2/library/os.html#os.pathsep) là cách an toàn nền tảng để cho biết dấu phân tách được sử dụng giữa các mục nhập đường dẫn trong hệ thống' $ PATH' hoặc biến môi trường '% PATH%'. Tuy nhiên, tôi sẽ không ** ủng hộ câu trả lời này bởi vì IMO không có gì để chỉnh sửa các biến môi trường trong thời gian chạy; IMO nên được đặt trong khi cài đặt bằng 'setup.py'. Thay vào đó tôi nghĩ rằng [chọn câu trả lời] (http://stackoverflow.com/a/2980501/1020470) hiện các trick! –

+2

@MarkMikofski Thats ngớ ngẩn. Bất kỳ ứng dụng nào chỉnh sửa biến môi trường là ứng dụng duy nhất nhìn thấy thay đổi. Chúng không tồn tại. Nó sẽ là một cơn ác mộng an ninh nếu họ làm vậy. setup.py không thể thay đổi các biến môi trường cho ứng dụng đang chạy anyways. Chỉnh sửa môi trường của bạn cho nội dung trái tim của bạn. – Tritium21

+0

@ tritium21 đó không phải là lý do cho nhận xét của tôi, mặc dù tôi nghĩ rằng tôi đã bối rối khi đặt 'PATH' và' sys.path'. Nói chung tôi nghĩ rằng bất cứ điều gì là mạnh mẽ, đơn giản và thực hành rộng rãi là tốt nhất. IMO thêm vị trí của DLL vào 'PATH' không mạnh bằng việc sử dụng đường dẫn đầy đủ của DLL. –

10

Mở rộng về câu trả lời của Matthew:

import os.path 
dll_name = "MyCDLL.dll" 
dllabspath = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + dll_name 
myDll = ctypes.CDLL(dllabspath) 

này sẽ chỉ hoạt động từ một kịch bản, không phải là giao diện điều khiển cũng không từ py2exe.

+0

Tôi thích sử dụng os.path.sep nói chung, nhưng có bất kỳ cài đặt Windows nào không sử dụng ';' cho một dấu phân cách đường? –

+1

Dấu tách đường dẫn này là dấu tách thư mục, tức là '\' trên Windows.Điều này có một cách tiếp cận khác với bạn, tải dll thông qua đường dẫn tệp tuyệt đối của nó thay vì sửa đổi biến môi trường PATH. Tôi nghĩ rằng tôi thích của bạn nhiều hơn, vì nó có một dự phòng để tải dll hệ thống mặc định nếu một trong những không được cung cấp. – fmark

+5

['os.path.join'] (http://docs.python.org/2/library/os.path.html#os.path.join) dễ dàng hơn nhiều trên các ngón tay và mắt. EG: 'os.path.abspath (os.path.join (os.path.dirname (__ file__), dll_name))' –

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