如何使用MSVC调试器调试从MATLAB调用的Python调用的C ++代码?

时间:2018-09-05 05:01:47

标签: python c++ visual-studio matlab debugging

我的设置

  • 给出一些Legacy™C ++代码
  • 使用使用Python ↔ C/C++ API的包装器,该包装器将被编译成.pyd文件
  • 有很多使用此.pyd文件的Legacy™Python代码
  • 然后从MATLAB调用此Python代码
  • MATLAB R2018a / Python 3.6 / C ++ 11 / Windows 10 / MSVC 2017社区
  • 这种设置是严格的,也就是说,所有这些代码在各种不同的上下文中被数百个人使用;这种非理想的设置已经是最佳的折衷方案

问题

  • 由于C ++代码中某处存在AccessViolation®,MATLAB崩溃。

很显然,MATLAB无法“浏览” .pyd二进制文件以确定根本原因,所以这就是我要做的所有事情。

我尝试过的事情

    • 使用MSVC2017,以.pyd模式(Debug)构建setup.py build --debug
    • 在MATLAB中:pyversion 'c:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\python.exe'
    • 真的需要来烦恼真的
    • 重新启动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(在所有位置的here中都找到了...)
    • 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'(首先确保已在MSVC上下文中安装了Python3.6调试环境)。
    • 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 AGAIN ,并且不要忘记重新附加到MSVC AGAIN 中的MATLAB.exe进程。
    • 这一次它至少继续执行Python代码,但是在具有相同{{1的每个导入模块(numpyscipy等)上触发}}和以前一样……
    • 放弃Python3.6。
    • 使用全新的非MSVC安装的Python 3.7从顶部重试,包括调试符号等。
    • 在MATLAB中:ImportError
    • pyversion 'c:\wherever\Python37_64\python.exe'哦。是的我忘了。重新启动MATLAB 再次,在 AGAIN 上方运行<speak_angrily_through_teeth>命令,运行令人讨厌的MATLAB代码,因为忘记重新连接MSVC而在拔头发时进行SCREAM,重新启动MATLAB < strong> AGAIN ,因为它显然崩溃了,重新连接了MSVC,运行了令人不快的MATLAB代码pyversion
    • Success!在MATLAB触发断点后,MSVC转到我的API代码。此处触发断点:

      </speak_angrily_through_teeth>

      其中

      PyObject *module = PyModule_Create(&moduledef);
      

      下载Python 3.7源代码后,我可以进行更深入的研究。 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 }; 调用是包装器,它在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

      似乎不太可能导致我的AccessViolation®。进入int _PyImport_IsInitialized(PyInterpreterState *interp) { if (interp->modules == NULL) return 0; return 1; } 最终使我意识到:我实际上是在调试Python / C ++ API而不是我的代码...

问题

  • 该死的!!为什么在使用Python3.6的MATLAB中进行调试如此困难呢?什么是“正确”的方法?我在(在线)文档中找不到很多东西……
  • Python 3.7 C / C ++ API是否存在可能导致此问题的已知问题?
  • 我做错了什么/愚蠢吗?关于如何更有效地在C ++代码中发现问题的任何提示/指针?

0 个答案:

没有答案