VSCode 联合调试Python/C++

  • 测试环境
  • 编写C++扩展
    • 1. 编写C++实现:`myadd.cpp`
    • 2. 编写要调用该扩展的Python脚本: `myscript.py`
    • 3. 编写setup脚本
    • 4. 编译安装
  • 使用gdb启动测试程序
    • 1. 安装gdb工具:
    • 2. 使用gdb测试是否可用:
  • GDB中STL的pretty print
  • VSCode调试Python调用的C++动态库
    • 1. 打开VSCode->打开工程文件夹
    • 2. 调试配置
    • 3. 运行python程序
    • 4. attach开始调试
    • 5. 完成调试,按红色插头断开连接,python进程继续运行。
  • 参考

  熟悉深度学习框架的同学都了解,如Tensorflow,Pytorch,Mxnet等都是提供Python前端编程接口,而后端是采用C/C++实现的。想要深入了解这些框架的源码,需要一些工程实践的基础,其中有一项便是Python/C++代码的联合调试。很多IDE如Pycharm,Clion等只支持一种语言的调试,对联合调试支持不好,网上的资料也很少。Visual Studio这个宇宙第一IDE倒是支持联合调试,不过VS不支持跨平台,只能在Windows运行。因此本文就选择了Vscode实现Python/C++代码的联合调试。一是它跨平台,二是通过插件支持多语言代码编辑以及调试。

测试环境

  • Ubuntu 18.04
  • vscode 1.59.1
  • Python 插件 2021.10.1365161279
  • C++插件 1.6.0
  • Python 3.7
  • g++ 7.5.0
  • gdb 8.1.1

编写C++扩展

1. 编写C++实现:myadd.cpp

#include <Python.h>static PyObject *method_myadd(PyObject *self, PyObject *args){int x, y, z = -1;/* Parse arguments */if(!PyArg_ParseTuple(args, "ii", &x, &y)){return NULL;}/* The actual bit of code I need */z = x + y;return PyLong_FromLong(z);
}static PyMethodDef myaddMethods[] = {{"myadd", method_myadd, METH_VARARGS, "Python interface for myadd C library function"},{NULL, NULL, 0, NULL}
};static struct PyModuleDef myaddmodule = {PyModuleDef_HEAD_INIT,"myadd","Python interface for the myadd C library function",-1,myaddMethods
};PyMODINIT_FUNC PyInit_myadd(void) {return PyModule_Create(&myaddmodule);
}

2. 编写要调用该扩展的Python脚本: myscript.py

import myaddprint("going to ADD SOME NUMBERS")
x = myadd.myadd(5,6)
print(x)

3. 编写setup脚本

from distutils.core import setup, Extensiondef main():setup(name="myadd",version="1.0.0",description="Python interface for the myadd C library function",author="wq_0608",author_email="xxxx@mail.com",ext_modules=[Extension("myadd", ["myadd.cpp"])],)if __name__ == "__main__":main()

  最简单的情况,我们使用Extention构造一个C/C++语言的扩展模块。

Extension("myadd", ["myadd.cpp"])

  第一个参数是模块的名称,第二个参数是一个list,里面包含所有的源文件。默认情况下采用c语言,如果我们使用C++语言,可以指定另一个参数language=“c++”

Extension("myadd", ["myadd.cpp"], language="c++")

4. 编译安装

我们可以执行以下命令进行安装:

$ python3 setup.py install
running install
running build
running build_ext...

也可以将它构建为动态链接库,可以从当前目录直接import。

$ python3 setup.py build_ext --inplace

现在myadd是可用的,我们可以运行以下命令检查它是否工作:

$ python3 myscript.py
going to ADD SOME NUMBERS
11

使用gdb启动测试程序

  调试Python程序,无论是手动调试还是IDE集成,都是基于pdb调试器进行的。而对于C++的调试我们则需要gdb(Linux), LLDB(mac), Visual Studio Windows Debugger(Windows)。无论单独用哪一个,都无法实现同时在Python程序和C++程序上打断点。所以只有使用Attach的方法进行调试。好在微软已经为我们开发了现成的一套工具,来在vscode上同时对Python和C++进行调试。

  ptvsd 是 Visual Studio 和 Visual Studio Code 中的 Python 调试器包,该调试引擎构建在开源 pydevd 之上。熟悉vscode python开发的同学可能都知道,ptvsd是用来进行远程调试的。服务器启动程序后,本地开发机通过ptvsd Attach到远程运行的程序上进行调试。它的功能可不止这么简单。ptvsd同时支持pdb,gdb调试器Attach到同一个进程上,以此实现Python和C++的联合调试。

  使用ptvsd联合调试python与c++这篇文章讲述了在VSCode中使用ptvsd联合调试Python与C++,但笔者按照文章尝试后,成功Attach到Python进程,但就是不跳进C++中断点。后来,看到使用gdb与python-gdb联合调试Python/C++这篇文章后遂改用gdb调试。下面以该途径做讲述,如有小伙伴知道怎么解决ptvsd联合调试问题欢迎交流!

1. 安装gdb工具:

根据Python官网使用GDB调试说明,针对不同系统安装不同的gdb工具:

Fedora:

  • sudo yum installgdb python-debuginfo

Ubuntu:

  • sudo apt-get install gdb python3.7-dbg

Centos*: 可以参考centos 7.x 版本下用gdb 调试

  • sudo yum install yum-utils
    sudo debuginfo-install glibc
    sudo yum install gdb python-debuginfo

2. 使用gdb测试是否可用:

$ gdb --args python myscript.py
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from python...done.
(gdb) b myadd.cpp:7
No source file named myadd.cpp.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (myadd.cpp:7) pending.
(gdb) r
Starting program: /usr/bin/python myscript.py
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
going to ADD SOME NUMBERSBreakpoint 1, method_myadd (self=self@entry=0x7f47fdccad10, args=args@entry=0x7f47fed75050) at myadd.cpp:7
7           if(!PyArg_ParseTuple(args, "ii", &x, &y)){(gdb) b myadd.cpp:12
Breakpoint 2 at 0x7f47fdac07ef: file myadd.cpp, line 12.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /usr/bin/python myscript.py
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
going to ADD SOME NUMBERSBreakpoint 1, method_myadd (self=<optimized out>, args=0x7fbd1bf56fa0) at myadd.cpp:7
7           if(!PyArg_ParseTuple(args, "ii", &x, &y)){(gdb) display z
1: z = <optimized out>
(gdb) n
3       static PyObject *method_myadd(PyObject *self, PyObject *args){1: z = <optimized out>
(gdb) n
7           if(!PyArg_ParseTuple(args, "ii", &x, &y)){1: z = -1
(gdb)

起始有(gdb)的表示在gdb的调试器环境运行命令。其中,

b:打断点

r:运行

display:设定在单步运行或其他情况中,自动显示的对应表达式的内容

n:使用命令n(next)或s(step),它们之间的区别在于:若有函数调用的时候,s会进入该函数而n不会进入该函数。因此,s就类似于VC等工具中的”step in”,n类似与VC等工具中的”step over”

  可以看到基本上已经可以使用gdb来对Python调用的C++共享库进行调试了。更进一步的,如果我们想通过VSCode来对库进行可视化的调试,又该如何处理呢?

GDB中STL的pretty print

  我们在使用gdb时,老是会对其显示的一些STL容器不能很好显示而感到不爽,从gdb7.0开始,支持python脚本导入gdb中,所以为了能让gdb中的vector更好的显示,需要在你的用户目录即~下放置一个.gdbinit文件和python的文件夹,这样操作之后,gdb在启动时就会运行这个.gdbinit从而对STL容器进行pretty print的支持,具体可以参见GDB Wiki的说明,也可参考VS Code中开启gdb的pretty-printer功能。

VSCode调试Python调用的C++动态库

1. 打开VSCode->打开工程文件夹

2. 调试配置

根据图1进入launch.json配置页面。

  此处讲解下attach的原理:attach是gdb的一个功能,用于对运行中的程序的状态进行监测,例如一些服务器中的进程不能直接以launch的方式启动,就只能以这种方式来监视。我们的项目中也同理,不能直接通过C++启动,所以需要python首先开启,然后在hello.cpp中设置getchar()或者pause进行中断进程,然后通过attach进程的方式来连接调试。(另外一种更直接的方式是通过上述所说的gdb进行调试,但这种只能通过gdb命令行的方式,可能习惯IDE的人不习惯,所以我找了这种用vscode的方式)

{"name": "(gdb) Attach","type": "cppdbg","request": "attach","program": "/usr/bin/python", //要启动的进程"processId": "${command:pickProcess}",//表示用手选的方式选择进行调试"MIMode": "gdb","additionalSOLibSearchPath": "${workspaceFolder}/build", //动态库所在位置"sourceFileMap": {"/build/glibc-S9d2JN": "/usr/src/glibc"}, //调试c时需要用到的库"logging": { "engineLogging": true },"setupCommands": [  //vscode打开gdb对STL容器的友好显示{"description": "Enable pretty-printing for gdb","text": "-enable-pretty-printing","ignoreFailures": true}]}

3. 运行python程序

  由于需要留时间给attach,所以运行python前需要在python脚本或c++代码中加入getchar()sleep()语句空转以等待attach。

$ python myscript.py

  或者在python脚本中打断点并在launch.json增加python程序的调试配置。

    {"name": "Python: 当前文件","type": "python","request": "launch","program": "${file}","console": "integratedTerminal","cwd": "${workspaceFolder}/test_demo"}

4. attach开始调试

attach前需要找到python进程号,有两种方式。

a. 运行ps aux | grep python:

root      4083  0.0  0.6 970112 205348 ?       Sl   Nov08   0:15 /root/.vscode-server/bin/3866c3553be8b268c8a7f8c0482c0c0177aa8bfa/node /root/.vscode-server/extensions/ms-python.vscode-pylance-2021.11.0/dist/server.bundle.js --cancellationReceive=file:d244b017462526dd28ca64cac58403d8f3ac9bc9f0 --node-ipc --clientProcessId=3954
root      6630  0.5  0.0 862548 16244 ?        Sl   07:37   0:00 /usr/bin/python /root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/adapter
root      6639  0.3  0.0 272404 15756 pts/8    Sl   07:37   0:00 /usr/bin/python /root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy/launcher 33327 -- /home/test_demo/myscript.py
root      6645  4.1  0.1 570468 35372 pts/8    Sl+  07:37   0:01 /usr/bin/python /root/.vscode-server/extensions/ms-python.python-2021.10.1365161279/pythonFiles/lib/python/debugpy --connect 127.0.0.1:37459 --configure-qt none --adapter-access-token e3958bb5dc3c5d3492e9316d6836aa704455f1348874d032ac682b2c734c9479 /home/test_demo/myscript.py
root      6709  0.0  0.0  11472  1092 pts/9    S+   07:37   0:00 grep --color=auto python

含有token的L4行就是目标进程,进程号为6645.

b. 使用VSCode的搜索
在VSCode的debug选择框中(如图2)点击倒三角切换到launch.json中配置的attach,此时会弹出图3中搜索框。

输入python或者运行的脚本名,选择较大进程号的那个就是目标进程。

正确attach后就会出现图4中红色插头:

5. 完成调试,按红色插头断开连接,python进程继续运行。

参考

  1. 调试Python调用的C++共享库
  2. gdb使用方法简介
  3. gdb调试Python动态链接库
  4. 使用c/c++编写python扩展(二)- Vscode Python C++联合调试
  5. Example debugging mixed Python C++ in VS Code

VSCode 联合调试Python/C++相关推荐

  1. 【工具】VScode|Linux 中怎么调试 Python 项目比较方便?又名 VScode 怎么调试 Python 项目(兼容环境Ubuntu18.04)

    使用过 Anaconda.Jupyter.Pycharm.VScode.VS2022.pdb 这几个 IDE 去编写 python 项目或者维护 python 环境,各有各的优缺点,但 VScode ...

  2. 成功解决 vscode远程调试python

    welcome to my blog 微软新出的插件, 非常方便远程调试, 不需要改动代码,简单9步, 配置远程调试环境 第一步 按ctrl+shift+x, 输入remote development ...

  3. vscode写python爬虫_如何在vscode中调试python scrapy爬虫

    HDOJ 2393. Higher Math Higher Math Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/327 ...

  4. vscode 调试python 无法连接远程服务器_vscode 远程调试python的方法

    此文介绍了vscode 远程调试python的方法,分享给大伙,具有如下: 实验环境 远程服务器:京东云,1核2G,centos7.3 64bit 本地环境配置 安装vscode,实验用的版本是1.1 ...

  5. vscode python 远程调试_vscode 远程调试python的方法

    vscode 远程调试python的方法 发布时间:2019-10-14 15:32 来源:互联网 当前栏目:web技术类 本文介绍了vscode 远程调试python的方法,分享给大家,具有如下: ...

  6. 【conda】——新建32位python环境,vscode无法调试

    1. 新建32位 conda 环境 激活一个conda A环境,将其设置成32位,然后再新建一个conda B环境,这样在 conda B 中用pip 安装的软件就都是32bit的了. 设置成32bi ...

  7. 软件_手把手教vscode配置c++,python开发环境

    原创:软件_手把手教vscode配置c++,python开发环境 之前主用Python作为项目开发语言,将项目迁移到arm边缘盒子上后发现arm的cpu不给力,软件速度低于预期,所以计划将部分程序改为 ...

  8. qt与python互联_PYQT5 vscode联合操作qtdesigner的方法

    除了使用pycharm外,还可使用vscode来操作pyqt,方法如下: 1. 在vscode中配置相关的pyqt的相关 根据自己实际情况修改第一项pyqt的路径 2. 创建一个文件夹,右键,最后一项 ...

  9. 在vscode中加参数调试-python

    在vscode中加参数调试-python 有时会遇到需要带有命令行参数的debug,因此需要在vscode的配置文件lanuch.json中添加命令行参数 解决方案 1.首先需要找到lanuch.js ...

最新文章

  1. 一个c/c++分布式框架ZMQ或者ZeroMQ, 介绍和win下安装使用方法
  2. Java算法试题--猜字母/杀人游戏
  3. NIS服务器介绍及搭建
  4. http协议状态码和web错误解决总结
  5. python单链表操作_单链表的创建、增删改查等操作(Python实现)
  6. 20220216-MISC-BUUCTF-另外一个世界-winhex,ASCII转换-FLAG- ZIP文件提取并修复-假如给我三天光明-ZIP改RAR,摩丝电码波形转换-神秘龙卷风brainfuck
  7. ★Linux磁盘配额的使用 ★——牛刀小试
  8. jsp 中的时间格式化
  9. iOS 不通过改变url 与web JS 交互
  10. 【干货】2021年中国主要经济指标预测-中国科学院.pdf(附下载链接)
  11. 不同微服务独立数据库,如何保障微服务架构下的数据一致性
  12. 回顾 | Apache Flink Meetup ·上海站(附PPT下载链接)
  13. android 模拟器好用哪个,安卓模拟器哪个好用 常用安卓模拟器性能大盘点
  14. 一个案例,看懂用户画像如何做出效益
  15. 用Python求三角形面积
  16. LoRa和NB-IoT会长期共存吗?
  17. 格密码初步学习记录(三)SVP
  18. 马哥N46班第一次月考
  19. 如何进行网站seo优化推广?
  20. (信贷风控八)行为评分卡模型(B卡)的介绍

热门文章

  1. 「建议收藏」我想进阿里,我该怎么做?
  2. 几句话概括理查德成熟度模型(RESTful)
  3. VMware15安装macOS Mojave 10.14.6(18G87)
  4. VLC和WebRTC等开源库关于硬解软解的策略
  5. 基于深度学习的视频检测(一)
  6. sql语句中where、group by、having、order by 是否可以使用别名
  7. 从ceph集群中删除MDS server
  8. chatGPT的对手,Claude注册教程
  9. unity-贴图压缩格式
  10. 怎么把计算机原有用户数据删除,电脑怎么清除数据