python c 联合_使用c/c++编写python扩展(二)- Vscode Python C++联合调试

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

测试环境Ubuntu 18.04

vscode 1.41

Python 插件 2020.2.63990

C++插件 0.26.3

Anaconda (Python 3.7)

g++ 7.40

gdb 8.1

编写一个简单的Python c++扩展

我们编写一个简单的c++扩展,实现新建文件并且往文件中写一些内容的功能。

fputsmodule.c

#define PY_SSIZE_T_CLEAN#include

static PyObject *StringTooShortError = NULL;

static PyObject *method_fputs(PyObject *self, PyObject *args, PyObject *kw) {

char *str, *filename = NULL;

int bytes_copied = -1;

/* Parse arguments */

char *kwlist[] = {"content", "filename", NULL};

if(!PyArg_ParseTupleAndKeywords(args, kw, "ss", kwlist, &str, &filename)) {

return NULL;

}

if (strlen(str) < 10) {

/* Passing custom exception */

PyErr_SetString(StringTooShortError, "String length must be greater than 10");

return NULL;

}

FILE *fp = fopen(filename, "w");

bytes_copied = fputs(str, fp);

fclose(fp);

return (PyObject *)Py_BuildValue("i", bytes_copied);

}

static PyMethodDef FputsMethods[] = {

{"fputs", method_fputs, METH_VARARGS | METH_KEYWORDS, "Python interface for fputs C library function"},

{NULL, NULL, 0, NULL}

};

static struct PyModuleDef fputsmodule = {

PyModuleDef_HEAD_INIT,

"fputs",

"Python interface for the fputs C library function",

-1,

FputsMethods

};

PyMODINIT_FUNC PyInit_fputs(void) {

/* Assign module value */

PyObject *module = PyModule_Create(&fputsmodule);

/* Initialize new exception object */

StringTooShortError = PyErr_NewException("fputs.StringTooShortError", NULL, NULL);

/* Add exception object to your module */

PyModule_AddObject(module, "StringTooShortError", StringTooShortError);

return module;

}

from distutils.core import setup, Extension

def main():

setup(name="fputs",

version="1.0.0",

description="Python interface for the fputs C library function",

author="hanbing",

author_email="beatmight@gmail.com",

ext_modules=[Extension("fputs", ["fputsmodule.c"])])

if __name__ == "__main__":

main()

具体可以参考我的另一篇文章。韩冰:使用c/c++编写python扩展(一):定义模块函数与异常​zhuanlan.zhihu.com

我们使用以下命令编译我们的Python扩展

python setup.py build_ext --inplace

接下来编写一个简单的调用脚本

import fputs

fputs.fputs("hello world! You are good!", "hello.txt")

print("hello world!")

使用ptvsd启动测试程序

调试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。

pip install ptvsd # 注意确认版本在4.0以上

接下来,在我们的测试程序fputs_test.py中添加以下代码

import argparse

parser = argparse.ArgumentParser()

parser.add_argument("--ptvsd", action="store_true", help="是否启动ptvsd调试。")

args = parser.parse_args()

if args.ptvsd:

import ptvsd

ptvsd.enable_attach(address =('127.0.0.1', 10010), redirect_output=True)

ptvsd.wait_for_attach()

import fputs

fputs.fputs("hello world! You are good!", "hello.txt")

print("hello world!")

这段代码的具体含义可以参考微软的官方文档Remote Debugging章节https://code.visualstudio.com/docs/python/debugging​code.visualstudio.com

接下来我们使用--ptvsd参数运行程序

python fputs_test.py --ptvsd

配置launch.json

熟悉vscode的同学都知道,调试的关键在于配置launch.json。我们需要一个Python代码的调试配置,一个C++代码的调试配置,具体如下。

{

"version": "0.2.0",

"configurations": [

{

"name": "Python Attach (local) proc 0",

"type": "python",

"request": "attach",

"pathMappings": [

{

"localRoot": "${workspaceFolder}", // You may also manually specify the directory containing your source code.

"remoteRoot": "${workspaceFolder}", // Linux example; adjust as necessary for your OS and situation.

}

],

"port": 10010,

"host": "localhost"

},

{

"name": "GDB Attach proc 0",

"type": "cppdbg",

"request": "attach",

"program": "/home/hanbing/anaconda3/bin/python",

"processId": "${command:pickProcess}",

"MIMode": "gdb"

}

]

}

其中第一个配置与远程调试Python的配置基本相同,只是我们attach的目标进程也在本地启动,代码路径的映射都是本地路径所以配置为${workspaceFolder}即可。这其中第二个配置则是gdb调试的配置。由于我们运行的python代码本质上是运行可执行程序 python,而Python又c++编写,所以可以直接对“python”程序进行调试。由于gdb使用attach模式进行调试需要指定目标程序的进程Id,所以我们在"processId"字段指定"${command:pickProcess}"意为启动调试时进行选择。启动该调试时,只需在vscode的对话窗口中搜索 “fputs_test.py”程序对应的id就行了。

配置完成后我们只需依次启动这两个调试配置即可开始调试。

视频演示Vscode Python/C++联合调试https://www.zhihu.com/video/1213936360442515456

注意事项

gdb使用attach模式进行调试时,需要root权限,所以在启动gdb的调试配置时可能需要输入密码获得临时的root权限,请确保你的当前用户可以获得sudo的权限。我在演示的过程中直接使用了root用户。在我的测试过程当中,使用普通用户权限在启动是可能会出现无法输入密码的情况,对此我在https://github.com/microsoft/vscode-cpptools​github.com

上提了一个issuehttps://github.com/microsoft/vscode-cpptools/issues/4988​github.com

该issue已经有人回复,具体解决方法可以参考以下链接:https://github.com/Microsoft/MIEngine/wiki/Troubleshoot-attaching-to-processes-using-GDB​github.com

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值