在上一篇(3:在Python中调用C++的结构体和类 https://blog.csdn.net/sdust_dx/article/details/80612694 )中,简单写了python如何调用C++的动态库,以及简单的传参。
在实际用的时候,我发现直接传递std::string 的时侯,有的时候会有问题,虽然没有具体研究到底是为什么。推测可能的问题是c_char_p 本来是指针,用来传递 sting 可能会有某些隐含的问题。
本帖更多的是抛砖引玉,请大神留言讲解一下其中的奥义。
先看看C++导出库的代码
extern "C"
{
// 返回值为 string
DLLEXPORT std::string __stdcall getVersion();
// 输入原来是 string,后来改成了 char* + length 的形式
DLLEXPORT bool __stdcall setParamFils(char* cfgFile, int len1, char* weightFile, int len2, float tTHresh = 0.5);
// 输出本来是想写成 string类型,但是调用的时候出错了。于是分开写成了两段。
DLLEXPORT int __stdcall detectImg_str(char* imgFilename, int len);
// 获取上面检测的文本类型结果
DLLEXPORT const char* __stdcall getDetectResult();
}
python调用的时候
myDll = ctypes.CDLL('myCPP.dll')
myDll.getVersion.restype = ctypes.c_char_p # 这样即可转换字符串数据了
tVersion = yoloDll.getVersion() # 获得返回值
# 将 c_char_p 转成python的 str
s = "";
for i in range(0, len(tVersion)):
s += chr(tVersion[i])
print('version = ', s) # 返回值打印为:( version = 1.0)
print("version = ", (tVersion)) # 返回值打印为:( version = b'1.0')
...
...
myDll.getDetectResult.restype = ctypes.c_char_p # 这样即可转换字符串数据了
ret = myDll.getDetectResult()
s = "";
for i in range(0, len(ret)):
s += chr(ret[i])
print('result = ', s) # 返回值打印为:( result = 855,76,33,20,0,0,0.301567 )
最初的时候,c++中的代码是这样写的:
DLLEXPORT std::string __stdcall detectImg_str(char* imgFilename, int len);
本来以为会像 getVersion() 一样能够获得正确的输出结果,但是获取的结果是乱码,完全不对。
按理说这两个方法的返回值应该是等效的,都能获取到才正常,偏偏不是这样。后来有位朋友说将返回值修改成 char* ,于是返回值终于能够在Python中正常获取了。至于原因,仍然未能搞清楚。希望高手能解惑