С++ с вложением Python: сбой, если Python не установлен
Я развиваюсь в Windows, и я искал везде, не найдя никого, кто говорил об этом.
Я сделал приложение С++ на своем рабочем столе, в которое встроен Python 3.1 с помощью MSVC. Я связал python31.lib и включил python31.dll в папку запуска приложения вместе с исполняемым файлом. Он отлично работает. Мой код расширения и встраивания определенно работает, и сбоев нет.
Я отправил папку запуска моему другу, у которого нет Python, и приложение врезается для него во время этапа настройки сценариев.
Несколько часов назад я попробовал приложение на своем ноутбуке с установленным Python 2.6. У меня такое же поведение при столкновении, как и у моего друга, и через отладку выяснилось, что это был вызов Py_Initialize(), который терпит неудачу.
Я установил Python 3.1 на свой ноутбук без изменения кода приложения. Я побежал, и он работает отлично. Я удалил Python 3.1, и приложение снова сработало. Я добавил код в свое приложение, чтобы динамически связать его с локальной python31.dll, чтобы убедиться, что он его использует, но я все равно получаю сбой.
Я не знаю, требуется ли интерпретатору больше, чем DLL для запуска или что. Я не смог найти никаких ресурсов на этом. Документация на Python и другие руководства, похоже, никогда не рассматривают, как распространять ваши приложения на C/С++, которые используют вложение Python, не устанавливая локально локальный Python. Я знаю, что это больше проблема в Windows, чем в Unix, но я видел несколько приложений Windows C/С++, которые встраивают Python локально, и я не уверен, как они это делают.
Что еще мне нужно, кроме DLL? Почему это работает, когда я устанавливаю Python и перестаю работать, когда я его удалю? Похоже, это должно быть так тривиально; может быть, поэтому никто не говорит об этом. Тем не менее, я не могу объяснить, как справиться с этой проблемой.
Спасибо вам заблаговременно.
Ответы
Ответ 1
В дополнение к pythonxy.dll вам также нужна вся библиотека Python, то есть содержимое папки lib, а также модули расширения, то есть содержимое папки DLL. Без стандартной библиотеки Python даже не запустится, так как он пытается найти os.py(в 3.x; string.py в 2.x). При запуске он импортирует несколько модулей, в частности site.py.
Существуют различные местоположения, где он ищет стандартную библиотеку; в ваших случаях он в конечном итоге находит это в реестре. Прежде чем использовать имя исполняемого файла (как установлено через Py_SetProgramName), пытаясь найти ориентир; он также проверяет файл python31.zip, который должен быть зашифрованной копией стандартной библиотеки. Он также проверяет переменную окружения PYTHONHOME.
Вы можете лишить библиотеку вещи, которые вам не нужны; существуют различные инструменты, которые вычисляют зависимости статически (особенно в модуле).
Если вы хотите свести к минимуму количество файлов, вы можете
- связывать все модули расширения статически с вашим pythonxy.dll или даже связывать pythonxy.dll статически в ваше приложение
- используйте инструмент замораживания; это позволит связать байтовый код стандартной библиотеки с вашим pythonxy.dll.
- (альтернативно, 2.) используйте pythonxy.zip для стандартной библиотеки.
Ответ 2
Ницца. И если вы не хотите zip, скопируйте Python26\DLLs и Python26\lib в каталог exe как:
.\myexe.exe
.\python26.dll
.\Python26\DLLs
.\Python26\lib
И затем установите PYTHONHOME с помощью API Py_SetPythonHome(). По-видимому, этот API не входит в список "разрешенных" вызовов до Py_Initialize();
Ниже работал у меня в Windows (Python не установлен):
#include "stdafx.h"
#include <iostream>
#include "Python.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char pySearchPath[] = "Python26";
Py_SetPythonHome(pySearchPath);
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\n");
//cerr << Py_GetPath() << endl;
Py_Finalize();
return 0;
}
Хорошо, что путь поиска относительный w.r.t exe. Py_GetPath может показать вам, где все это ищет модули.
Ответ 3
Я хотел добавить дополнительную информацию для других, у которых все еще могут быть проблемы с этим, как и я. В конечном итоге я смог получить свое приложение, используя метод, предложенный пользователем sambha, то есть:
Program Files (x86)\
MyApplicationFolder\
MyApplication.exe
python27.dll
Python27\
DLLs\ (contents of DLLs folder)
Lib\ (contents of Lib folder)
... с одним важным : мне также нужно установить MSVCR90.DLL. Я использую Python 2.7 и, видимо, python27.dll требует MSVCR90.DLL(и, возможно, другие MSVC * 90.DLL).
Я решил это путем загрузки, установки и запуска пакета 'vcredist_x86.exe' из http://www.microsoft.com/en-us/download/details.aspx?id=29. Я думаю, хотя я не уверен, что вам нужно сделать это таким образом, по крайней мере, на Win7, а не просто разместить MSVC * 90.DLL вместе с вашим .exe, как вы, возможно, уже в прошлом. Установщик Microsoft помещает файлы и регистрирует их особым образом под Win7.
Я также пробовал использовать .zip файл, но это не сработало, даже если установлен MSVCR90.DLL.
Ответ 4
Для меня с Python27 работал zip стандартной библиотеки Python.
Я закрепил содержимое Lib и dll и убедился, что вложенную папку python27-sub или lib или dll нет. то есть просто zip с именем python27.zip, содержащий все файлы.
Я скопировал этот zip и python27.dll вместе с исполняемым файлом.