在Windows上使用VSCode调试Python C/C++扩展

15

问题概述

我正在开发一个自己的Python C扩展程序,以提高特定代码段的性能。我想调试这个扩展程序,但是到目前为止我还没有成功。我已经尝试了一些链接,比如这个来自Nadiah的链接这个来自Bark的链接,但我总是遇到同样的问题:我无法在C代码的任何断点处停止。

我尝试的方法

想法是将Python作为主进程运行,并将编译后的C代码附加到该主进程上。以下是最小可再现示例

Python文件

import os
import greet

pid = os.getpid()

test=2.2

greet.greet('World')

print("hi")

如您所见,我甚至检索了进程ID,以便在附加C代码时可以选择此ID。C代码如下:

C代码

#include <Python.h>

static PyObject *
greet_name(PyObject *self, PyObject *args)
{
    const char *name;

    if (!PyArg_ParseTuple(args, "s", &name))
    {
        return NULL;
    }
    
    printf("Helllo %s!\n", name);

    Py_RETURN_NONE;
}

static PyMethodDef GreetMethods[] = {
    {"greet", greet_name, METH_VARARGS, "Greet an entity."},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef greet =
{
    PyModuleDef_HEAD_INIT,
    "greet",     /* name of module */
    "",          /* module documentation, may be NULL */
    -1,          /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
    GreetMethods
};

PyMODINIT_FUNC PyInit_greet(void)
{
    return PyModule_Create(&greet);
}

我使用GCC 8.1编译C代码,通过运行python setup.py install命令:

安装文件

import os

from setuptools import setup, Extension

os.environ["CC"] = "g++-8.1.0"

_DEBUG = True
_DEBUG_LEVEL = 0
# extra_compile_args = sysconfig.get_config_var('CFLAGS').split()
extra_compile_args = ["-Wall", "-Wextra"]
if _DEBUG:
    extra_compile_args += ["-g3", "-O0", "-DDEBUG=%s" % _DEBUG_LEVEL, "-UNDEBUG"]
else:
    extra_compile_args += ["-DNDEBUG", "-O3"]

setup(
    name='greet',
    version='1.0',
    description='Python Package with Hello World C Extension',
    ext_modules=[
        Extension(
            'greet',
            sources=['greetmodule.c'],
            py_limited_api=True,
            extra_compile_args=extra_compile_args)
    ],
)

我甚至使用O0选项来拥有所有调试符号。

启动JSON文件

"configurations": [
    {
        "name": "(gdb) Attach",
        "type": "cppdbg",
        "request": "attach",
        "program": "venv/Scripts/python",
        "processId": "${command:pickProcess}",
        "MIMode": "gdb",
        // "miDebuggerPath": "/path/to/gdb",
        "setupCommands": [
            {
                "description": "Enable pretty-printing for gdb",
                "text": "-enable-pretty-printing",
                "ignoreFailures": true
            }
        ]
    },
    {
        "name": "Python: Current File",
        "type": "python",
        "request": "launch",
        "program": "${file}",
        "console": "integratedTerminal"
    }
]

我遵循的调试步骤

  1. 在Python文件中添加断点,运行启动配置“Python: Current File”,等待到达断点。
  2. 运行“(gdb) Attach”启动配置,选择路径包含“/.vscode/”的Python解释器。在这种情况下,在Windows中,不会像在Linux中那样提示输入用户密码。
  3. 在C ++文件中设置断点。
  4. Python调试器当前停止在断点处。从调试器“(gdb) Attach”切换回另一个调试器“Python: Current File”,然后按F5(继续)。

在这最后一步中,vscode应该自动在Python和C++代码之间跳转两个调试器,但我无法实现此行为。

我能够单独调试Python和C程序,但无法共同调试。


你在这个链接中遇到了什么问题?[https://nadiah.org/2020/03/01/example-debug-mixed-python-c-in-visual-studio-code/] - Divyessh
嗨@Divyessh,似乎你提供的链接已经失效了...我猜你在参考我帖子中提供的第一个链接。一切都顺利进行直到最后一步(第五步)。不同之处在于,在Windows中,我不会被提示输入超级用户密码。此外,尽管(gdb)附加任务正在运行,但我无法在设置的C代码断点处停止。链接基于Linux,因此在Windows中调试时可能会有所不同。 - David Duran
我遇到了类似的问题,而且我也尝试了你尝试过的大部分解决方案。你有没有尝试在 GitHub 的 vscode 问题中提出这个问题? - axel_ande
嗨@axel_ande。是的,我在两周前在VsCode C++扩展的Github上开了一个问题(https://github.com/microsoft/vscode-cpptools/issues/6974)。让我们看看是否有人能够解决它。 - David Duran
2个回答

3

在Windows上调试Python C++代码时,您应该在launch.json文件中使用"(Windows) Attach"配置。为了简化将C++调试器附加到Python调试器的过程,您可以使用VScode扩展程序"Python C++ Debug"。

Nidiah和Bark的两个示例都是基于Linux的。

在Windows上,您可以将C/C++代码编译为带有DEBUG信息的.dll文件,并在Python中使用ctypes加载它。


1
嗨@BeniBenj。我已经点赞了,因为它看起来很有前途。让我深入测试一下,然后再回到你这里。顺便说一句,我没有使用ctypes而是C扩展。这会有什么区别吗?另外一个侧面说明,(gdb)也应该可以工作(在使用g++编译时),因为我已经在Windows(启动模式)中单独测试过它,并且它可以工作... - David Duran
这个解决方案可能适用于 ctypes,但我尝试使用 Cython 进行编码的 C 扩展时未能成功。 - David Duran

0

Windows 的限制:

Cygwin 和 MinGW 上的 GDB 无法中断正在运行的进程。要在应用程序正在运行(未在调试器下停止)时设置断点,或者暂停正在调试的应用程序,请在应用程序的终端中按 Ctrl-C


点击此处获取更多信息 链接 - Divyessh
我不确定这个限制是否与我的问题有关...我的意思是,我可以调试一个独立的C/C++应用程序。你是说在Windows上使用“(gdb) attach”模式无法进行调试吗? - David Duran
不,我的意思是我们不能在Windows上使用gdb来设置断点。 - Divyessh
实际上,如果我只运行一个独立的C/C++应用程序,我确实可以在Windows上使用断点(使用gdb)...问题只出现在尝试调试连接到Python的C时... - David Duran
请访问评论中的链接,希望您能找到一些相关信息。 - Divyessh
是的,我访问了你评论中的链接。不幸的是,我无法解决我的问题。无论如何,感谢你的帮助! - David Duran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,