使用 Visual Studio 代码调试 Pybind11 扩展 (MacOS)

Debugging Pybind11 extension with Visual Studio Code (MacOS)

我最近一直在使用 pybind11,现在我已经掌握了它的窍门,我对它感到很兴奋。这是一件了不起的作品。执行 pybind11 的最后一块工具拼图是调试部分。我使用以下指南使用 lldb 进行命令行调试:

Debugging pybind11 with lldb

我花了一些时间尝试使用 Visual Studio 代码进行调试,但收效甚微。第一个问题是,为了设置 attach 配置,您需要指定 python 可执行文件(不是进程 ID)。如果您有多个活动的 python 进程,我不知道这应该如何工作,这种情况经常发生。

先放一边,我设置了一个launch配置指向ipython可执行文件,这样用起来最方便了。当我尝试开始调试时,我得到这个:

谁能解释一下?

如果我将可执行文件更改为普通 Python,我会在调试控制台中看到:

Could not initialize Python interpreter - only native expressions will be available.
Launching: /Users/andy/anaconda3/envs/SciPy37/bin/python

但如果进入终端window,我可以成功输入Python表达式,并触发代码中设置的断点。万岁!但是还有一个问题。当我的一个扩展程序需要加载另一个 dylib 时,它找不到它。

>>> import block_test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dlopen(/Users/andy/Dropbox (Personal)/Developer/AudioDev/GenericDSP/Common/SciPy/BlockTest/build/block_test.cpython-37m-darwin.so, 2): Symbol not found: _vDSP_vsmul
  Referenced from: /Users/andy/Dropbox (Personal)/Developer/AudioDev/GenericDSP/Common/SciPy/BlockTest/build/block_test.cpython-37m-darwin.so
  Expected in: flat namespace
 in /Users/andy/Dropbox (Personal)/Developer/AudioDev/GenericDSP/Common/SciPy/BlockTest/build/block_test.cpython-37m-darwin.so

这有点道理 because_vDSP_vsmul 是 Apple DSP 加速库的一部分。但我没有得到的是,当我使用本文开头提到的命令行调试技术时,我没有遇到这个问题 post。显然这与 dylib 的找到方式有某种关系,但为什么这与命令行情况不同?

对这些问题的任何帮助都会很棒。让调试工作在 Visual Studio 中工作 代码是 Python 和 C++

之间绝对惊人的互操作性所缺少的部分

我想出了如何附加到进程调试以使用 Visual Studio 代码 iPython 和 Mac OS Catalina。 launch.json 中的以下代码将起作用:

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "lldb",
      "request": "launch",
      "name": "Debug",
      "program": "path_to/bin/python",
      "args": [],
      "cwd": "${workspaceFolder}/build"
    },
    { 
      "name": "Debug Attach",
      "type": "lldb",
      "request": "attach",
      "program": "path_to/bin/python",
      "processId": "${command:pickProcess}",
      "MIMode": "gdb"
  },
  ]
}

首先,在尝试开始调试之前,在终端 window 中启动 IPython 这样您就可以附加一个进程。

我最初 运行 遇到 VSC 的问题,抱怨 json 文件中没有 "program" 条目,这在附加到进程时似乎无关紧要。它实际上可能完全不相关,但您必须添加它才能使事情正常进行。我没有尝试为程序参数输入虚假条目来查看该值是否重要。

另一个细节 - 有时 VSC 中的断点似乎没有启用,当您创建它们时,您会得到一个空心圆而不是红点。但似乎无论如何你都会遇到断点。但是,根据我以前的经验,最好在 iPython under test after attaching to the process 中导入包,以获得最佳效果。

我偶然发现了这个 SO post How to configure VS Code to be able to step into a shared library (.so) that is loaded when debugging a Python script? 而不是必须附加到已经 运行 的调试器,我能够从 VSCode 中启动 gdb ]:

    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch 1123",
            "type": "cppdbg",
            "request": "launch",
            "program": "/usr/bin/python3",
            "args": ["${file}"],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

从这个 launch.json 设置中,我能够单步执行设置断点的 C++ 代码并调试我的 C++ 代码。但是,正如之前 SO post 的评论中提到的,我不确定在调试会话期间是否有一种方法可以在 python 和 C/C++ 代码之间流动。如果试图在我的 python 文件上放置断点,我也会“在创建它们时得到一个空心圆而不是红点”。

我在 macOS 10.14.5 中使用 LLDB 实现这个时遇到了问题。 对我有用的是使用以下配置为 VS Code 安装“vadimcn.vscode-lldb”扩展:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "lldb",
            "request": "attach",
            "name": "Attach pid",
            "pid": "${command:pickProcess}", // use ${command:pickProcess} to pick other users' processes,
        },
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "stopOnEntry": true,
            "env": {
                "PYTHONPATH": "${workspaceFolder}/build"
            }
        },
        {
            "type": "lldb",
            "request": "launch",
            "name": "LLDB Python",
            "program": "/usr/local/bin/python3",
            "args": [
                "${file}"
            ],
            "cwd": "${workspaceFolder}",
            "stopOnEntry": false,
            "env": {
                "PYTHONPATH": "${workspaceFolder}/build"
            },
        },
    ]
}

使用 lldb (LLDB Python) 启动 python 或我首先启动一个 python 调试会话 (Python: Current File),我可以附加到 (Attach pid)之后。第二个选项的好处是能够在 python 和 C++ 中设置断点。