Pycharm等调用dll时使用VS调试:附加到进程(Attach to Process)

前言

Python与C语言联合编程时,使用python调用dll库是很常见的情况,因为可以通过将常用函数或复杂函数封装成C语言提高效率,但如何调试是一个问题。

本文环境:VS 2013 Ultimate + Pycharm 2017 Community

正文

1.编写dll文件

新建VS项目,选择“Win32控制台应用程序”或“Win32项目”(甚至“空项目”)都可以,在向导中选择“DLL”。我个人是勾选“空项目”以及关闭“安全开发生命周期(SDL)检查”,减少不必要的麻烦。

#define EXPORT __declspec(dllexport)

在一开始可以会加这样一个宏定义来方便以后的书写,这样在需要外部调用的函数前加EXPORT即可。

2.编译一次dll文件

与普通程序编译步骤相似,生成解决方案即可。

只有生成dll文件之后,其他程序如pycharm才能调用这个文件,才能开始调试过程,因此需要先编译一次,在Debug或Release目录下得到dll文件,同时还有pdb文件等(若是x64平台编译,则还有一个x64上级目录)。

注:根据需要应更改vs编译平台配置或更换python版本,因为64位python无法直接调用32位dll,32位python也无法直接调用64位dll,即vs编译平台版本应与python版本对应。在“配置管理器”中可以新建x64编译平台:

3.python脚本调用dll库

python调用dll库需要使用ctypes包,资料很丰富,可自行学习——>官方文档,示例如下:

import numpy as np
import numpy.ctypeslib as npct
from ctypes import c_int


#定义float型连续指针的数据类型
p_float = npct.ndpointer(dtype=np.float32, ndim=1, flags='CONTIGUOUS')
#导入dll库,注意这里的路径是第一次编译的文件位置
libcd = npct.load_library("D:\\Document\\VS\\dll_demo\\x64\\Debug\\test", ".")
#定义返回值类型
libcd.test.restype = None
#定义参数类型
libcd.test.argtypes = [p_float, c_int, c_int, c_int]
#调用函数
libcd.test(a,b,c,d)

 若只在pycharm内进行调试,在进行到最后的调用步骤时,调试器无法进入C代码中,会很不方便,尤其是带有指针的参数传递时,往往只会得到一个出错的内存位置,并不知道发生了什么问题。

4.联合调试

先在pycharm内调用dll库函数之前设一个断点,让调试器停到这个位置。

然后打开dll文件所在的VS项目,在dll库的代码中设断点。 

选择VS上面选项中的“调试(Debug)”——>“附加到进程(Attach to Process)”,选择进程进行附加(Attach)

注意使用pycharm调试脚本时,应附加的进程是python而不是pycharm,同理以其他方式调试时(如参考资料中的cmd)也应选择附加到python进程。

在pycharm中继续运行,即可运行到C程序中的断点处,就可以和普通C程序一样调试了。

这种方法具有很强的普遍性,不得不说VS真的很强。

参考资料

StackOverflow大佬的精辟总结

另一种从配置VS调试器的角度得到的方法,两种方法本质是一样的

对我的启发文章和一些可补充内容

亟待解决的问题

最近使用VS 2017 Enterprise和Pycharm 2018 Pro联合调试dll时报了下面的问题:

PYDEV DEBUGGER WARNING:
sys.settrace() should not be used when the debugger is being used.
This may cause the debugger to stop working correctly.
If this is needed, please check: 
http://pydev.blogspot.com/2007/06/why-cant-pydev-debugger-work-with.html
to see how to restore the debug tracing back correctly.
Call Location:
  File "D:\JetBrains\PyCharm 2018.3.3\helpers\pydev\_pydevd_bundle\pydevd_comm.py", line 382, in _on_run
    r = self.sock.recv(1024)


PYDEV DEBUGGER WARNING:
sys.settrace() should not be used when the debugger is being used.
This may cause the debugger to stop working correctly.
If this is needed, please check: 
http://pydev.blogspot.com/2007/06/why-cant-pydev-debugger-work-with.html
to see how to restore the debug tracing back correctly.
Call Location:
  File "D:\JetBrains\PyCharm 2018.3.3\helpers\pydev\pydevd.py", line 877, in do_wait_suspend
    time.sleep(0.01)

 

猜你喜欢

转载自blog.csdn.net/Tele_Anti_Nomy/article/details/85797328