Как отладить код C ++, который вызывается из Python, который вызывается из MATLAB, используя отладчик MSVC? - PullRequest
0 голосов
/ 05 сентября 2018

Моя настройка :

  • С учетом некоторого кода Legacy ™ C ++
  • Используя оболочки, использующие API Python ↔ C / C ++ , он компилируется в .pyd файл
  • Существует множество кода Legacy ™ Python, который использует этот .pyd файл
  • Этот код Python вызывается из MATLAB
  • MATLAB R2018a / Python 3.6 / C ++ 11 / Windows 10 / MSVC 2017 Community
  • Эта установка жесткая, т. Е. Весь этот код используется сотнями людей в самых разных контекстах; эта неидеальная установка уже является наилучшим компромиссом

Проблема :

  • Сбой MATLAB из-за нарушения прав доступа где-то в коде C ++.

Очевидно, что MATLAB не может "просмотреть" двоичный файл .pyd, чтобы определить основную причину, поэтому это все, что мне нужно сделать.

Что я пробовал :

    • Используя MSVC2017, создайте .pyd в режиме Debug (setup.py build --debug).
    • В MATLAB: pyversion 'c:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\python.exe'
    • Будьте действительно раздражены необходимостью перезапустить MATLAB, прежде чем вы сможете это сделать.
    • После перезапуска MATLAB и запуска указанной команды в MSVC: DebugAttach to Process → выберите MATLAB.exe
    • Запустите код MATLAB, который вызывает сбой.
    • MATLAB / Python жалуется: Python Error: ImportError: DLL load failed: The specified module could not be found.
    • Попробуйте то же, что и в 1., на этот раз переименуйте файл my_pylib.pyd в my_pylib_d.pyd (как найдено здесь всех мест ...)
    • MATLAB / Python жалуется: Python Error: ImportError: cannot import name 'my_pylib'
    • Попробуйте то же самое, что и 2., на этот раз с указанием pyversion 'c:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\python_d.exe' (сначала убедитесь, что среда отладки Python3.6 была установлена ​​в контексте MSVC).
    • Be REALLY раздражает необходимость перезапуска MATLAB Every. Fucken. Время. Вы запускаете эту команду!
    • Перейдите на сайт поддержки MathWorks и вставьте Запрос о возможностях, чтобы попытаться исправить это в R2019a
    • Перезапустите MATLAB, заново подключите MSVC к MATLAB.exe и повторите с начала
    • MATLAB / Python все еще жалуется: Python Error: ImportError: cannot import name 'my_pylib'
    • Повторите 3., на этот раз вынуждая MATLAB также использовать python36_d.dll, потому что каким-то образом этот механизм кажется сломанным в MATLAB.
    • SCREAM IN RAGE, потому что вам нужно перезапустить MATLAB СНОВА и не забыть повторно присоединиться к процессу MATLAB.exe в MSVC СНОВА .
    • На этот раз, по крайней мере, продолжается выполнение кода Python, но он отключается на каждом импортированном модуле (numpy, scipy и т. Д.) С тем же ImportError, что и раньше ...
    • Откажись от Python3.6.
    • Повторите попытку сверху, используя новую не-MSVC установку Python 3.7, включая символы отладки и т. Д.
    • в MATLAB: pyversion 'c:\wherever\Python37_64\python.exe'
    • <speak_angrily_through_teeth> Ох. Да уж. Я забыл Перезапустите MATLAB СНОВА , запустите pyversion команду выше СНОВА , запустите некорректный код MATLAB, ВИНТ ВЫТЯНИТЕ ВОЛОСЫ, потому что вы забыли повторно присоединить MSVC, перезапустите MATLAB СНОВА потому что он, очевидно, потерпел крах, повторно подключите MSVC, запустите некорректный код MATLAB </speak_angrily_through_teeth>
    • Успех ! MSVC переходит к моему API-коду после того, как MATLAB вызывает точку останова. Точка останова срабатывает здесь:

      PyObject *module = PyModule_Create(&moduledef);
      

      , где

      static struct PyModuleDef moduledef = 
      {
          PyModuleDef_HEAD_INIT,
          "my_pylib",
          NULL,
          sizeof(struct module_state),
          my_pylib_methods,
          NULL,
          my_pylib_traverse,
          my_pylib_clear,
          NULL
      };
      

      После загрузки исходного кода Python 3.7 я могу копнуть немного глубже. Вызов PyModule_Create - это оболочка, которая вызывает следующую функцию в Objects/moduleobject.c:

      PyObject *
      PyModule_Create2(struct PyModuleDef* module, int module_api_version)
      {
          if (!_PyImport_IsInitialized(PyThreadState_GET()->interp))
              Py_FatalError("Python import machinery not initialized");
          return _PyModule_CreateInitialized(module, module_api_version);
      }
      

      где точка останова находится внутри предложения if(). Это означает, что moduledef даже не имеет значения. _PyImport_IsInitialized() - это функция в Python/import.c:

      int
      _PyImport_IsInitialized(PyInterpreterState *interp)
      {
          if (interp->modules == NULL)
              return 0;
          return 1;
      }
      

      , что, по-видимому, не является вероятным кандидатом, который может стать причиной моего нарушения прав доступа®. Переход к PyThreadState_GET() наконец заставил меня осознать: я фактически отлаживаю API Python / C ++ вместо своего кода ...

Вопросы :

  • Что тон, черт возьми! Почему отладка в MATLAB с использованием Python3.6 так чертовски сложна ?! Каков «правильный» способ сделать это? Я не могу найти много в (онлайн) документации для этого ...
  • Известна ли проблема с API-интерфейсом Python 3.7 C / C ++, которая может вызывать это?
  • Я что-то делаю неправильно / тупо? Любые советы / указатели о том, как я могу найти проблему в моем коде C ++ более эффективно?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...