2010-06-05 9 views
19

У меня есть модуль Python, wrapper.py, который обертывает C DLL. DLL находится в той же папке, что и модуль. Поэтому я использую следующий код, чтобы загрузить его:Python ctypes: загрузка DLL из относительного пути

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

Это работает, если я исполню wrapper.py из своей собственной папки. Если, однако, я запускаю его из другого места, он терпит неудачу. Это потому, что ctypes вычисляет путь относительно текущего рабочего каталога.

Мой вопрос: есть ли способ, которым я могу указать путь к DLL относительно оболочки вместо текущего рабочего каталога? Это позволит мне отправить их вместе и позволить пользователю запускать/импортировать оболочку из любого места.

+1

Я использую подход в [выбранном ответе] (http://stackoverflow.com/a/2980501/1020470), но в одном случае у меня была dll, которая импортировала экспорт из другой DLL, и она не загружалась , Решением было сначала загрузить другую dll, 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, который работает! –

ответ

20

Вы можете использовать os.path.dirname(__file__), чтобы получить каталог, в котором находится исходный файл Python.

+0

Большое спасибо. Это именно то, что я искал. –

+0

Относительный путь, как это, работает отлично, не нужно использовать 'os.path.abspath()' или добавляя этот путь к '$ PATH' ('% PATH% '). Одно предостережение, если ваша dll требует другую dll, тогда вам придется загрузить это тоже, прежде чем загружать этот, см. Мой комментарий по вопросу OP. –

6

Я всегда добавляю каталог, в котором находится моя DLL. Это работает:

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

Обратите внимание, что если вы используете py2exe, это не работает (потому что __file__ не установлен). В этом случае, вы должны полагаться на sys.executable атрибутов в (полные инструкции по http://www.py2exe.org/index.cgi/WhereAmI)

+0

['os.pathsep'] (http://docs.python.org/2/library/os.html#os.pathsep) является безопасным для платформы способом указать разделитель, используемый между записями пути в системе' $ PATH' или "% PATH%". Однако я бы не стал ** защищать этот ответ, потому что ИМО неспокойно редактировать переменные среды во время выполнения; IMO они должны быть установлены во время установки с помощью 'setup.py'. Вместо этого я думаю, что [выбранный ответ] (http://stackoverflow.com/a/2980501/1020470) делает трюк! –

+2

@MarkMikofski Thats глупо. Любое приложение, редактирующее переменные среды, является единственным приложением, которое видит изменение. Они не сохраняются. Если бы они это сделали, это был бы кошмар безопасности. setup.py не может изменять переменные среды для запущенного приложения в любом случае. Отредактируйте свою среду до вашего сердца. – Tritium21

+0

@ tritium21, что не было причиной моего комментария, хотя я думаю, что запутался в настройках 'PATH' и' sys.path'. В общем, я считаю, что все, что нужно, просто и широко практикуется. ИМО, добавляющая расположение DLL в 'PATH', не так прост, как просто использование полного пути DLL. –

10

Опираться на ответ от Матфея:

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

Это будет работать только из сценария, а не консоль, ни от py2exe.

+0

Мне нравится использование os.path.sep в целом, но есть ли какие-либо установки Windows, которые не используют ';' для разделителя путей? –

+1

Этот разделитель путей является разделителем каталогов, то есть «\» в Windows.Это относится к вашему подходу, загружая DLL через его абсолютный путь к файлу, а не изменяя переменную окружения PATH. Я думаю, что мне больше нравится ваш, поскольку он имеет резерв для загрузки системной DLL по умолчанию, если он не поставляется. – fmark

+5

['os.path.join'] (http://docs.python.org/2/library/os.path.html#os.path.join) намного проще на пальцах и глазах. EG: 'os.path.abspath (os.path.join (os.path.dirname (__ file__), dll_name))' –

Смежные вопросы