Компиляция PythonService.cpp из сборки расширения python win32

Мне нужна помощь в сборке 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. Возможно ли это сделать без компиляции всего проекта?
Был бы благодарен за любую помощь!

Спасибо!
Алексей

2

Решение

В конце концов я нашел решение своего вопроса (не без помощи ответа @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

Другие решения

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)

  • Скачать оригинал pywin32 от: [GitHub]: mhammond / pywin32 — (b222)pywin32-b222.zip). «$ {PYWIN32_SRC_DIR} \ win32 \ SRC \ PythonService.cpp«идентичен его корреспонденту из URL ты упомянул
  • Создать каталог и cd к нему (должно быть пустым). Это будет % ROOT_DIR%, и все пути, которые я собираюсь использовать, будут относительными к нему (кроме, конечно, для абсолютных), и это будет каталог по умолчанию (если не указан)
  • Распакуйте загруженный почтовый индекс куда-нибудь. Нам (напрямую) нужно от этого:

    • «$ {PYWIN32_SRC_DIR} \ win32 \ SRC \ PythonService.cpp«- как вы уже упоминали, исходный код
    • «$ {PYWIN32_SRC_DIR} \ win32 \ SRC \ PythonServiceMessages.mc«- текстовый файл сообщения

    Я скопировал их в каталог под названием ЦСИ:

    E:\Work\Dev\StackOverflow\q048931801>dir /b
    src
    
    E:\Work\Dev\StackOverflow\q048931801>dir /b "src"PythonService.cpp
    PythonServiceMessages.mc
    
  • Поскольку сборка включает в себя ресурсы и Пользовательские шаги сборки (что я не очень хорош в этом), а также это не связано с большим количеством файлов, я не собираюсь использовать IDE
  • Следующим лучшим подходом будет использование Makefiles, но с тех пор VStudio есть ошибка [MSDN]: ntwin32.mak не найден:

    • Это влияет VStudio 2015 также
    • Требуется одноразовое исправление
    • Я сделал исправление на моей машине, и оно работает, но вы, скорее всего, не сделали на своем, и я не хочу излишне обременять вас этим шагом

    Я собираюсь сделать все вручную

  • Настройка Среда VStudio:

  • Скомпилируйте файл сообщения в файл ресурса — используя 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 раздел):

    • PyWinTypesModule.cppGetPythonTraceback функция (строки 1142 — 1235)
    • PyUnicode.cppPyWin_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) — вам придется адаптировать их в соответствии с вашими путями:
      1. «C: \ Install \ x64 \ Python \ Python \ 3.5 \ включают» (питон дорожка)
      2. «Е: \ Work \ Dev \ Fati \ WinBuild \ OPSWpython27 \ SRC \ pywin32-B222 \ win32 \ ЦСИ» (pywin32 дорожка)
  • Связать все вместе — используя 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) — адаптируйте его под свои:
      1. «C: \ Install \ x64 \ Python \ Python \ 3.5 \ LIBS (питон дорожка)
  • Последний шаг перед запуском сервиса. Так как это зависит от 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'
    
0

По вопросам рекламы [email protected]