Мне нужна помощь в сборке pythonservice.exe (PythonService.cpp) из https://github.com/kovidgoyal/pywin32/tree/master/win32/src.
Говорят (https://github.com/kovidgoyal/pywin32), что VS2015 требуется, поэтому я скачал версию сообщества. Я открыл новый консольный проект win32 и импортировал в исходные файлы только PythonService.cpp.
В настройках проекта у меня есть:
Включить каталоги: C:\Python27_32bit\include;C:\pywin32-master\win32\src;$(VC_IncludePath);$(WindowsSDK_IncludePath);
Библиотечные каталоги: C:\Python27\Lib\site-packages\win32\libs;C:\Python27_32bit\libs;C:\pywin32-master\win32\src;$(LibraryPath);C:\pywin32-master\lib\x32\win32\libs;
Теперь при сборке я получаю неразрешенную ошибку внешнего символа:
1>PythonService.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) char * __cdecl GetPythonTraceback(struct _object *,struct _object *,struct _object *)" (__imp_?GetPythonTraceback@@YAPADPAU_object@@00@Z)
GetPythonTraceback определен в PyWinTypesmodule.cpp, но когда я добавляю его в свой проект, он выдает другие ошибки, требующие других неразрешенных функций. Я не хочу компилировать весь проект win32. Все, что мне нужно, это pythonservices.exe. Возможно ли это сделать без компиляции всего проекта?
Был бы благодарен за любую помощь!
Спасибо!
Алексей
В конце концов я нашел решение своего вопроса (не без помощи ответа @CristiFati!). Я загрузил https://github.com/mhammond/pywin32/tree/b222 и использовал скрипт setup.py для сборки всего пакета. Кроме того, я установил необходимый пакет SDK (для python 2.6+ Microsoft Windows SDK для Windows 7 и .NET Framework 4 (версия 7.1)). Немного покопавшись, я обнаружил, что компиляция и компоновка выполняются в Visual C ++ для Python 9.0 и ниже. Это рецепты компиляции и компоновки для pythonservice.pyd и pythonservice.exe (списки python для параметра cmd для вызовов os.spawnv (os .P_WAIT, исполняемый файл, cmd):
Для pythonservice.pyd:
['"C:\\Users\\username\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\WinSDK\\Bin\\x64\\mc.exe"','-h', 'win32/src', '-r', 'build\\temp.win-amd64-2.7\\Release\\win32/src', 'win32/src/PythonServiceMessages.mc']
['"C:\\Users\\username\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\WinSDK\\Bin\\x64\\rc.exe"','/fobuild\\temp.win-amd64-2.7\\Release\\win32/src/PythonServiceMessages.res','build\\temp.win-amd64-2.7\\Release\\win32/src\\PythonServiceMessages.rc']
['"C:\\Users\\username\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\VC\\Bin\\amd64\\cl.exe"','/c', '/nologo', '/Ox','/W3','/GS', '/DNDEBUG', '/MD', '-DDISTUTILS_BUILD', '-D_CRT_SECURE_NO_WARNINGS','-Icom/win32com/src/include', '-Iwin32/src', '-IC:\\Python27\\include', '-IC:\\Python27\\PC','"-IC:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.1A\\include"', '/Tpwin32/src/PythonService.cpp','/Fobuild\\temp.win-amd64-2.7\\Release\\win32/src/PythonService.obj', '-DPYSERVICE_BUILD_DLL', '/Zi','/Fdbuild\\temp.win-amd64-2.7\\Release\\servicemanager_vc.pdb', '/EHsc', '/DUNICODE', '/D_UNICODE', '/DWINNT']
['"C:\\Users\\username\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\VC\\Bin\\amd64\\link.exe"', '/DLL', '/nologo', '/INCREMENTAL:NO', '/LIBPATH:C:\\Python27\\libs', '/LIBPATH:C:\\Python27\\PCbuild\\amd64', '/LIBPATH:C:\\Python27\\PC\\VS9.0\\amd64', '/LIBPATH:build\\temp.win-amd64-2.7\\Release', '"/LIBPATH:C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.1A\\lib\\x64"', 'user32.lib', 'ole32.lib', 'advapi32.lib', 'shell32.lib', '/EXPORT:initservicemanager', 'build\\temp.win-amd64-2.7\\Release\\win32/src/PythonServiceMessages.res', 'build\\temp.win-amd64-2.7\\Release\\win32/src/PythonService.obj', '/OUT:build\\lib.win-amd64-2.7\\win32\\servicemanager.pyd', '/IMPLIB:build\\temp.win-amd64-2.7\\Release\\win32/src\\servicemanager.lib', '/MANIFEST:NO', '/MACHINE:amd64', '/BASE:0x1e7d0000', '/DEBUG', '/PDB:build\\temp.win-amd64-2.7\\Release\\servicemanager.pdb']
Для pythonservice.exe:
['"C:\\Users\\username\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\VC\\Bin\\amd64\\cl.exe"','/c', '/nologo', '/Ox', '/W3', '/GS-', '/DNDEBUG', '/MD', '-DDISTUTILS_BUILD', '-D_CRT_SECURE_NO_WARNINGS','-Icom/win32com/src/include', '-Iwin32/src', '-IC:\\Python27\\include', '-IC:\\Python27\\PC','"-IC:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.1A\\include"','/Tpwin32\\src\\PythonService.cpp', '/Fobuild\\temp.win-amd64-2.7\\Release\\pythonservice\\win32\\src\\PythonService.obj','/Zi', '/Fdbuild\\temp.win-amd64-2.7\\Release\\pythonservice_vc.pdb', '/EHsc', '/DUNICODE', '/D_UNICODE', '/DWINNT']
['"C:\\Users\\username\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\WinSDK\\Bin\\x64\\rc.exe"','-DDISTUTILS_BUILD', '-D_CRT_SECURE_NO_WARNINGS', '-Icom/win32com/src/include', '-Iwin32/src', '-IC:\\Python27\\include','-IC:\\Python27\\PC', '"-IC:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.1A\\include"','/fobuild\\temp.win-amd64-2.7\\Release\\pythonservice\\win32\\src\\PythonService.res', 'win32\\src\\PythonService.rc']
['"C:\\Users\\username\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python\\9.0\\VC\\Bin\\amd64\\link.exe"','/nologo', '/INCREMENTAL:NO', '/LIBPATH:C:\\Python27\\libs', '/LIBPATH:C:\\Python27\\PCbuild\\amd64','/LIBPATH:C:\\Python27\\PC\\VS9.0\\amd64', '/LIBPATH:build\\temp.win-amd64-2.7\\Release','"/LIBPATH:C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.1A\\lib\\x64"', 'user32.lib', 'advapi32.lib', 'ole32.lib','shell32.lib', 'build\\temp.win-amd64-2.7\\Release\\pythonservice\\win32\\src\\PythonService.obj','build\\temp.win-amd64-2.7\\Release\\pythonservice\\win32\\src\\PythonService.res','/OUT:build\\lib.win-amd64-2.7\\win32\\pythonservice.exe','/MANIFESTFILE:build\\temp.win-amd64-2.7\\Release\\pythonservice\\win32\\src\\pythonservice.exe.manifest','/SUBSYSTEM:CONSOLE', '/MACHINE:amd64', '/DEBUG', '/PDB:build\\temp.win-amd64-2.7\\Release\\pythonservice.pdb']
['mt.exe', '-nologo', '-manifest','build\\temp.win-amd64-2.7\\Release\\pythonservice\\win32\\src\\pythonservice.exe.manifest.orig','-outputresource:build\\lib.win-amd64-2.7\\win32\\pythonservice.exe;1']
['C:\\Python27\\python.exe', 'C:\\Python27\\Lib\\site-packages\\win32\\lib\\win32verstamp.py', '--version=2.7.222.1', '--comments=https://github.com/mhammond/pywin32', '--original-filename=pythonservice.exe','--product=PyWin32', '--quiet', 'build\\lib.win-amd64-2.7\\win32\\pythonservice.exe']
1улица вещь, которую я вижу здесь, объединяет Python 2.7 а также VStudio 2015. В соответствии с [Python]: WindowsCompilers, за VStudion 2015 (или же 14,0), вы должны использовать Python 3.5 или же Python 3.6 (У меня бывшая).
Проверьте [SO]: установка Simstring (python) в Windows (ответ @ CristiFati) — (1улица часть), о совместимости и ограничениях в отношении:
Также некоторая (основная) информация о строительстве С код на Выиграть: [SO]: ошибка LNK2005 в форме Windows CLR (ответ @ CristiFati)
cd
к нему (должно быть пустым). Это будет % ROOT_DIR%, и все пути, которые я собираюсь использовать, будут относительными к нему (кроме, конечно, для абсолютных), и это будет каталог по умолчанию (если не указан)Распакуйте загруженный почтовый индекс куда-нибудь. Нам (напрямую) нужно от этого:
Я скопировал их в каталог под названием ЦСИ:
E:\Work\Dev\StackOverflow\q048931801>dir /b src E:\Work\Dev\StackOverflow\q048931801>dir /b "src"PythonService.cpp PythonServiceMessages.mc
Следующим лучшим подходом будет использование Makefiles, но с тех пор VStudio есть ошибка [MSDN]: ntwin32.mak не найден:
Я собираюсь сделать все вручную
Настройка Среда VStudio:
Я использую ту использовать vcvarsall.bat ([MSDN]: Где находится файл vcvarsall.bat?) из командной строки
E:\Work\Dev\StackOverflow\q048931801>"c:\Install\x86\Microsoft\Visual Studio Community\2015\VC\vcvarsall.bat" amd64
amd64
потому что у меня только 64бит (x64 или же AMD64) версия Python 3.5 установленыСкомпилируйте файл сообщения в файл ресурса — используя mc.exe ([MSDN]: Компилятор сообщений (MC.exe))
E:\Work\Dev\StackOverflow\q048931801>mc "src\PythonServiceMessages.mc"MC: Compiling src\PythonServiceMessages.mc E:\Work\Dev\StackOverflow\q048931801>dir /b MSG00001.bin PythonServiceMessages.h PythonServiceMessages.rc src
Как видно, сгенерировано 3 новых файла
Скомпилируйте файл ресурса — используя rc.exe ([MSDN]: Ресурсный Компилятор)
E:\Work\Dev\StackOverflow\q048931801>rc /NOLOGO /r "PythonServiceMessages.rc" E:\Work\Dev\StackOverflow\q048931801>dir /b MSG00001.bin PythonServiceMessages.h PythonServiceMessages.rc PythonServiceMessages.res src
Сделано с ресурсами, переходя к коду (PythonService.cpp). Как вы уже упоминали, он не скомпилируется OOTB. Я не собираюсь перечислять все неудачные попытки, вместо этого я перечислю шаги, которые я предпринял, и покажу только окончательную (успешную) компиляцию. Таким образом, файл нуждается в коде из других файлов. Самый простой способ — скопировать его из других файлов и поместить в него. Я решил обклеить его # 1530 (как раз перед * Entry points
раздел):
GetPythonTraceback
функция (строки 1142 — 1235)PyWin_AutoFreeBstr::PyWin_AutoFreeBstr
, PyWin_AutoFreeBstr::~PyWin_AutoFreeBstr
, PyWin_AutoFreeBstr::SetBstr
(строки 204 — 219)Примените изменения вручную или сохраните:
--- PythonService.cpp.orig 2018-01-20 21:43:10.000000000 +0200
+++ PythonService.cpp 2018-02-23 20:02:20.186966800 +0200
@@ -1529,6 +1529,120 @@
}
}
+// @TODO: cfati - copied from PyUnicode.cpp (lines 204 - 219)
+PyWin_AutoFreeBstr::PyWin_AutoFreeBstr( BSTR bstr /*= NULL*/ )
+ : m_bstr(bstr)
+{
+ return;
+}
+
+PyWin_AutoFreeBstr::~PyWin_AutoFreeBstr()
+{
+ SysFreeString(m_bstr);
+}
+
+void PyWin_AutoFreeBstr::SetBstr( BSTR bstr )
+{
+ SysFreeString(m_bstr);
+ m_bstr = bstr;
+}
+
+
+// @TODO: cfati - copied from PyWinTypesModule.cpp (lines 1142 - 1235)
+// Function to format a python traceback into a character string.
+#define GPEM_ERROR(what) {errorMsg = "<Error getting traceback - " ## what ## ">";goto done;}
+char *GetPythonTraceback(PyObject *exc_type, PyObject *exc_value, PyObject *exc_tb)
+{
+ // Sleep (30000); // Time enough to attach the debugger (barely)
+ char *result = NULL;
+ char *errorMsg = NULL;
+ PyObject *modStringIO = NULL;
+ PyObject *modTB = NULL;
+ PyObject *obFuncStringIO = NULL;
+ PyObject *obStringIO = NULL;
+ PyObject *obFuncTB = NULL;
+ PyObject *argsTB = NULL;
+ PyObject *obResult = NULL;
+
+ /* Import the modules we need - cStringIO and traceback */
+#if (PY_VERSION_HEX < 0x03000000)
+ modStringIO = PyImport_ImportModule("cStringIO");
+#else
+ // In py3k, cStringIO is in "io"+ modStringIO = PyImport_ImportModule("io");
+#endif
+
+ if (modStringIO==NULL) GPEM_ERROR("cant import cStringIO");
+ modTB = PyImport_ImportModule("traceback");
+ if (modTB==NULL) GPEM_ERROR("cant import traceback");
+
+ /* Construct a cStringIO object */
+ obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO");
+ if (obFuncStringIO==NULL) GPEM_ERROR("cant find cStringIO.StringIO");
+ obStringIO = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obStringIO==NULL) GPEM_ERROR("cStringIO.StringIO() failed");
+
+ /* Get the traceback.print_exception function, and call it. */
+ obFuncTB = PyObject_GetAttrString(modTB, "print_exception");
+ if (obFuncTB==NULL) GPEM_ERROR("cant find traceback.print_exception");
+ argsTB = Py_BuildValue("OOOOO"+#if (PY_VERSION_HEX >= 0x03000000)
+ "i"+ // Py3k has added an undocumented 'chain' argument which defaults to True
+ // and causes all kinds of exceptions while trying to print a goddam exception
+#endif
+ ,
+ exc_type ? exc_type : Py_None,
+ exc_value ? exc_value : Py_None,
+ exc_tb ? exc_tb : Py_None,
+ Py_None, // limit
+ obStringIO
+#if (PY_VERSION_HEX >= 0x03000000)
+ ,0 // Goddam undocumented 'chain' param, which defaults to True
+#endif
+ );
+ if (argsTB==NULL) GPEM_ERROR("cant make print_exception arguments");
+
+ obResult = PyObject_CallObject(obFuncTB, argsTB);
+ if (obResult==NULL){
+ // Chain parameter when True causes traceback.print_exception to fail, leaving no
+ // way to see what the original problem is, or even what error print_exc raises
+ // PyObject *t, *v, *tb;
+ // PyErr_Fetch(&t, &v, &tb);
+ // PyUnicodeObject *uo=(PyUnicodeObject *)v;
+ // DebugBreak();
+ GPEM_ERROR("traceback.print_exception() failed");
+ }
+ /* Now call the getvalue() method in the StringIO instance */
+ Py_DECREF(obFuncStringIO);
+ obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue");
+ if (obFuncStringIO==NULL) GPEM_ERROR("cant find getvalue function");
+ Py_DECREF(obResult);
+ obResult = PyObject_CallObject(obFuncStringIO, NULL);
+ if (obResult==NULL) GPEM_ERROR("getvalue() failed.");
+
+ /* And it should be a string all ready to go - duplicate it. */
+ if (PyString_Check(obResult))
+ result = strdup(PyString_AsString(obResult));
+#if (PY_VERSION_HEX >= 0x03000000)
+ else if (PyUnicode_Check(obResult))
+ result = strdup(_PyUnicode_AsString(obResult));
+#endif
+ else
+ GPEM_ERROR("getvalue() did not return a string");
+
+done:
+ if (result==NULL && errorMsg != NULL)
+ result = strdup(errorMsg);
+ Py_XDECREF(modStringIO);
+ Py_XDECREF(modTB);
+ Py_XDECREF(obFuncStringIO);
+ Py_XDECREF(obStringIO);
+ Py_XDECREF(obFuncTB);
+ Py_XDECREF(argsTB);
+ Py_XDECREF(obResult);
+ return result;
+}
/*************************************************************************
*
как «ЦСИ \ PythonService.diff«Это различие. Видите [SO]: запускать / отлаживать UnitTests приложения Django из контекстного меню, вызываемого правой кнопкой мыши, в PyCharm Community Edition? (Ответ @ CristiFati) (Ямочный ремонт раздел) о том, как применять патчи на Win (в основном, каждая строка, начинающаяся с один «+» знак идет, и каждая строка, которая начинается с один «-« знак гаснет). я использую Cygwin:
E:\Work\Dev\StackOverflow\q048931801>"c:\Install\x64\Cygwin\Cygwin\AllVers\bin\patch.exe" "src\PythonService.cpp" "src\PythonService.diff"patching file 'src\PythonService.cpp'
Скомпилируйте код — используя cl.exe ([MSDN]: Компиляция программы на C / C ++)
E:\Work\Dev\StackOverflow\q048931801>cl /GS /W1 /Zc:wchar_t /I"." /I"c:\Install\x64\Python\Python\3.5\include" /I"e:\Work\Dev\Fati\WinBuild\OPSWpython27\src\pywin32-b222\win32\src" /Gm- /O2 /Zc:inline /fp:precise /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "WIN64" /D "NDEBUG" /D "BUILD_PYWINTYPES" /errorReport:prompt /WX- /Zc:forScope /Gd /MD /c "src\PythonService.cpp"Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x64 Copyright (C) Microsoft Corporation. All rights reserved. PythonService.cpp E:\Work\Dev\StackOverflow\q048931801>dir /b "*.obj"PythonService.obj
Аргументы стандартные ([MSDN]: параметры компилятора перечислены в алфавитном порядке), характерные для этого случая:
/D "BUILD_PYWINTYPES"
(макроопределение)/D "WIN64"
— 64 бит/I
) — вам придется адаптировать их в соответствии с вашими путями:
Связать все вместе — используя link.exe ([MSDN]: связь)
E:\Work\Dev\StackOverflow\q048931801>link /NOLOGO /MACHINE:X64 /SUBSYSTEM:CONSOLE /ERRORREPORT:PROMPT /LIBPATH:"c:\Install\x64\Python\Python\3.5\libs" /NXCOMPAT /DYNAMICBASE "kernel32.lib" "user32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "PythonService.obj" "PythonServiceMessages.res" /OUT:"PythonService.exe"Creating library PythonService.lib and object PythonService.exp E:\Work\Dev\StackOverflow\q048931801>dir /b "*.exe"PythonService.exe
Опять же, аргументы стандартные ([MSDN]: параметры компоновщика), характерные для этого случая:
/MACHINE:X64
— 64 бит/LIBPATH
) — адаптируйте его под свои:
Последний шаг перед запуском сервиса. Так как это зависит от python35.dll, Операционные системы должен знать, где его искать. Самый простой способ — добавить путь к %ДОРОЖКА% ([MSDN]: порядок поиска в библиотеке Dynamic-Link)
E:\Work\Dev\StackOverflow\q048931801>set PATH=%PATH%;c:\Install\x64\Python\Python\3.5 E:\Work\Dev\StackOverflow\q048931801>PythonService.exe P - Python Service Manager Options: -register - register the EXE - this should generally not be necessary. -debug servicename [parms] - debug the Python service. NOTE: You do not start the service using this program - start the service using Control Panel, or 'net start service_name'