当前位置: 首页 > 后端技术 > Python

Python调用C++类库(踩坑日志)

时间:2023-03-26 17:50:17 Python

Python调用C++类库(踩坑日志)原因在自动化工具的开发过程中,需要使用专业的仪器来测试射频参数,IQmeasure,而厂商提供的API只使用C++版本。客户端是用python(wxpython)开发的,所以遇到了python调用C++类库的问题。环境PyCharm2020python3.6.1232位(python3.8不能用,64位python不能用;其他版本没测试过)IQmeasure_SCPI.dll(供应商给的dll包)IQmeasure.chm(dll对应的文件)参考ctypes官方python文档使用前请先浏览ctypes官方文档新建工程(python使用3.6.1232位版本)将dll文件放到根目录下,创建main.py目录结构如下test├──IQmeasure_SCPI.dll├──venv└──main.py的基本用法如下(main.py):fromctypesimport*#Loaddllpackageiq=cdll.LoadLibrary('./IQmeasure_SCPI.dll')#Callmethodinit_result=iq.LP_Init(c_int(0),c_int(1))print('init_result:',init_result)#init_result:0#在此方法中,返回0表示成功#在原始C++文档中,方法如下:#intLP_Init(intIQtype=IQTYPE_XEL,inttesterControlMethod=1);知识点使用ctypes.cdll.LoadLibrary()加载dll包参数需要转成c类型(比如c_int(),不懂先看参考资料中ctypes的python官方文档)在C++中选择参数,使用python调用时不能省略。请在有返回值的方法中传入默认值fromctypesimport*#loaddllpackageiq=cdll.LoadLibrary('./IQmeasure_SCPI.dll')#hasreturnvalue#settingReturnvaluetypeiq.LP_GetErrorString.restype=c_char_p#设置初始值typeiq.LP_GetErrorString.argtypes=[c_int]msg=iq.LP_GetErrorString(c_int(10))print(msg)#b'Invalidanalysistype'#Converttostringstr_msg=msg.decode("utf-8")print(str_msg)#VSA编号超出范围。Try1-4.#在C++原文档中,方法如下:#char*LP_GetErrorString(interr)知识点是返回值时,使用.methodname.restype设置返回值类型。也可以使用类似的方法设置参数值。使用.methodname.argtypes设置参数类型。由于急于开发,所以没有深入研究,像int,char*#...省略加载dll#参数值为*type#使用byref(),把对应的类型包裹起来即可iq.LP_SetTesterMode(c_int(0),byref(c_int(1)),c_int(1))#在C++原文档中,方法如下:#intLP_SetTesterMode(intsignalMode=UP_TO_80MHZ_SIGNAL,int*selectedModules=NULL,intnumOfSelectedModules=1);,使用byref包裹引用类型参数#...省略加载dllversion=create_string_buffer(4096)iq.LP_GetVersion(version,4096)version_result=version.value.decode("utf-8")#在原始C++文档中,方法如下:#该方法会改变*buffer,需要在python中读取*buffer的值#boolLP_GetVersion(char*buffer,intbuf_size);知识点方法参数传入后,方法会改变原来的参数,需要读取改变后的参数新值首先创建一个buffer调用方法将buffer转换回完整的测试代码fromctypesimport*#loaddllpackageiq=cdll.LoadLibrary('./IQmeasure_SCPI.dll')#调用方法init_result=iq.LP_Init(c_int(0),c_int(1))print('init_result:',init_result)#init_result:0#在该方法中,返回0表示成功#在C++原文档中,方法如下:#intLP_Init(intIQtype=IQTYPE_XEL,inttesterControlMethod=1);#有返回值#设置返回值类型iq.LP_GetErrorString.restype=c_char_p#设置初始值类型iq.LP_GetErrorString.argtypes=[c_int]msg=iq.LP_GetErrorString(c_int(10))print(msg)#b'Invalidanalysistype'#Converttostringstr_msg=msg.decode("utf-8")print(str_msg)#VSA编号超出范围。Try1-4.#在原来的C++文档中,方法如下:#char*LP_GetErrorString(interr)#参数值为*type#使用byref(),把对应的类型包裹起来即可iq.LP_SetTesterMode(c_int(0),byref(c_int(1)),c_int(1))#在C++原文档中,方法如下:#intLP_SetTesterMode(intsignalMode=UP_TO_80MHZ_SIGNAL,int*selectedModules=NULL,intnumOfSelectedModules=1);version=create_string_buffer(4096)iq.LP_GetVersion(version,4096)version_result=version.value.decode("utf-8")#原C++文档中,方法如下:#该方法会改变*buffer,并且*buffer的值需要在python中读取#boolLP_GetVersion(char*buffer,intbuf_size);总结因为本人对C++了解不多,所以C++部分的解释和名词有偏差,勿怪水平有限,欢迎私信指正内容,我和罗小平已经在上面获取了开发实践