C++调用Python,包括参数传递及返回值的处理的教程都很多。但是对于中文字符作为参数传递时,会遇到编码问题而乱码甚至崩溃。经过搜集资料,终于解决乱码问题,特记录在此:

1、参数传递一般采用PyObject* objArg = Py_BuildValue("s", "Hello")构建参数,当输入参数为中文时,objArg则返回为空指针。原因是:Python为UTF-8编码,而C++中中文大多采用GBK编码。对于中文采用两个字节表示一个汉字,而此函数最终构建参数时还是按一个字节一个字节构建的,所以中文会构建失败。

2、构建中文参数可以采用该函数(PyObject*) PyUnicode_FromUnicode(const Py_UNICODE *u, Py_ssize_t size);此函数的参数为Unicode字符串和字符个数(中文两个字节算一个字符)。

3、GBK编码的字符如何转换为Unicode字符串:

3.1 若为windows下程序,可采用windows的宽字符转换API,具体实现为:

#include <windows.h>PyObject* StringToPyByWin(std::string str)
{int wlen = ::MultiByteToWideChar(CP_ACP, NULL, str.c_str(), int(str.size()), NULL, 0);wchar_t* wszString = new wchar_t[wlen + 1];::MultiByteToWideChar(CP_ACP, NULL, str.c_str(), int(str.size()), wszString, wlen);wszString[wlen] = '\0';PyObject* pobj = PyUnicode_FromUnicode((const Py_UNICODE*)wszString, wlen);delete wszString;return pobj;
}

该函数直接将string字符串转换为PyObject*,可直接使用;

3.2 若需要在其他平台使用,可采用Qt的QTextCodec实现string转换为QString(QString采用Unicode编码),具体实现代码如下:

#include <QString>
#include <QTextCodec>
#include <string>// std::string (GBK) -> QString(Unicode)
QString ToUnicode(const string& cstr)
{QTextCodec* pCodec = QTextCodec::codecForName("gb2312");if(!pCodec)return "";QString qstr = pCodec->toUnicode(cstr.c_str(), cstr.length());return qstr;
}

另,Qt实现QString转为string的代码如下:

// QString(Unicode) -> std::string (GBK)
string FromUnicode(const QString& qstr)
{QTextCodec* pCodec = QTextCodec::codecForName("gb2312");if(!pCodec)return ""; QByteArray arr = pCodec->fromUnicode(qstr);string cstr = arr.data();return cstr;
}

4、具体如何实现C++调用Python并实现中文参数的传递呢?综合上面的代码,下面附上完整源码,我采用Qt的方式转换中文编码。共3个文件,testCallPython.py、main.cpp和GBK.h:

testCallPython.py(Python文件)

#以UTF-8编码
def callTest(string):print('传入的字符串为:' + string)#返回结果reStr = 'Python返回值'return reStr

main.cpp(调用Python的C++文件)

#include <Python.h>
#include <iostream>
#include "GBK.h"
#include <windows.h>
using namespace std;PyObject* StringToPyByWin(std::string str)
{int wlen = ::MultiByteToWideChar(CP_ACP, NULL, str.c_str(), int(str.size()), NULL, 0);wchar_t* wszString = new wchar_t[wlen + 1];::MultiByteToWideChar(CP_ACP, NULL, str.c_str(), int(str.size()), wszString, wlen);wszString[wlen] = '\0';PyObject* pobj = PyUnicode_FromUnicode((const Py_UNICODE*)wszString, wlen);delete wszString;return pobj;
}PyObject* StringToPyByQt(std::string str)
{int sLen = GBK::ToUnicode(str).size();wchar_t* wChStr = new wchar_t[sLen + 1];GBK::ToUnicode(str).toWCharArray(wChStr);wChStr[sLen] = '\0';PyObject* pobj = PyUnicode_FromUnicode((const Py_UNICODE*)wChStr, sLen);delete wChStr;wChStr = NULL;return pobj;
}//测试调取python脚本
bool callTest(string str)
{//初始化python模块Py_Initialize();if (!Py_IsInitialized()){printf("初始化Python失败!\n");return false;}//导入sys模块PyRun_SimpleString("import sys");PyRun_SimpleString("sys.path.append('E:\\CallPython\\CallPython')");//存放脚本python脚本的目录(testCallPython.py文件)//导入testCallPython.py脚本模块PyObject* pModule = PyImport_ImportModule("testCallPython");if (!pModule){printf("读取Python脚本testCallPython失败!\n");return false;}//获取函数PyObject* pFunc = PyObject_GetAttrString(pModule, "callTest");if (!pFunc){printf("获取函数callTest失败!\n");return false;}//处理中文字符串PyObject* pKeyWord = StringToPyByQt(str);//以元组的形式打包参数PyObject* pArgs = PyTuple_New(1);PyTuple_SetItem(pArgs, 0, pKeyWord);PyObject* pReturn = PyEval_CallObject(pFunc, pArgs);//处理返回值char* result = new char[20];PyArg_Parse(pReturn, "s", &result);string reStr = GBK::FromUnicode(result);cout << "C++调用Python返回结果为:" << reStr << endl;//结束,释放python解释器Py_Finalize();return true;
}int main(int argc, char *argv[])
{callTest("This is 中文测试");cin.get();return 0;
}

GBK.h(Qt下中文转码)

#ifndef _QT_GBK_H
#define _QT_GBK_H#include <QString>
#include <QTextCodec>
#include <string>
using std::string;class GBK
{
public:// QString(Unicode) -> std::string (GBK)static string FromUnicode(const QString& qstr){QTextCodec* pCodec = QTextCodec::codecForName("gb2312");if(!pCodec)return ""; QByteArray arr = pCodec->fromUnicode(qstr);string cstr = arr.data();return cstr;}// std::string (GBK) -> QString(Unicode)static QString ToUnicode(const string& cstr){QTextCodec* pCodec = QTextCodec::codecForName("gb2312");if(!pCodec)return "";QString qstr = pCodec->toUnicode(cstr.c_str(), cstr.length());return qstr;}
};#endif

5、运行4中的程序,结果为:

注:采用Python3,python文件一定要采用UTF-8编码,否则会读取脚本失败;要使用GBK.h文件,必须导入QtCore模块。

解决C++调用Python中文乱码相关推荐

  1. 解决python中文乱码的方法

    解决python中文乱码的方法 参考文章: (1)解决python中文乱码的方法 (2)https://www.cnblogs.com/bobodeboke/p/11935876.html 备忘一下.

  2. shell 调用securecrt_securecrt导入xshell 解决xshell、SecureCRT中文乱码 - Linux - 服务器之家...

    securecrt导入xshell 解决xshell.SecureCRT中文乱码 发布时间:2017-04-14 来源:服务器之家 一.解决xshell 中文乱码 在xshell命令行里面 输入: l ...

  3. Java中文乱码破碎重组_总结彻底解决Spring MVC+Mybatis中文乱码问题

    Java对于新手最容易出现的问题就是中文乱码的问题.今天我就来总结一下彻底解决Spring mvc+Mybatis中文乱码的方案. 首先要看打一断点看一下Controller接收到参数值是否正常.如果 ...

  4. python判断汉字个数_python判断列表里数量python中文乱码问题大总结

    在运行这样类似的代码:#!/usr/bin/env python s="中文" print s 最近经常遇到这样的问题: 问题一:SyntaxError: Non-ASCII ch ...

  5. 解决Ubuntu下matplotlib中文乱码问题-以添加宋体:simsun为例

    解决Ubuntu下matplotlib中文乱码问题-以添加宋体:simsun为例 先从simsun官网上下载宋体字体库 : 查看matplotlib配置文件位置: import matplotlibp ...

  6. linux python乱码_linux下python中文乱码解决方案详解

    linux下python中文乱码解决方案详解 发布时间:2020-09-06 20:24:49 来源:脚本之家 阅读:68 1. 场景描述 linux服务器下安装了Anaconda3,执行Pyhton ...

  7. 在Visual Studio Code 中配置Python 中文乱码问题

    在Visual Studio Code 中配置Python 中文乱码问题 方法一:直接代码修改字符集 添加前四行代码 import io import sys #改变标准输出的默认编码 sys.std ...

  8. linux 下,解决tomcat服务器接收中文乱码的问题

    linux 下,解决tomcat服务器接收中文乱码的问题 参考文章: (1)linux 下,解决tomcat服务器接收中文乱码的问题 (2)https://www.cnblogs.com/taz372 ...

  9. 解决Http响应内容中文乱码问题

    解决Http响应内容中文乱码问题 参考文章: (1)解决Http响应内容中文乱码问题 (2)https://www.cnblogs.com/kongieg/p/10119588.html (3)htt ...

最新文章

  1. 数据模拟工具wgsim
  2. 【工业互联网】全球工业互联网十大最具成长性技术展望(2019-2020年)
  3. mybatis 查询之神坑
  4. ubuntu下 apt-get install 下载文件存放的位置
  5. 信息学奥赛一本通(1230:寻找平面上的极大点)
  6. linux 查看汉字编码方式
  7. ISA Server 2006速战速决实验指南(7) 创建元素-网络对象
  8. python html5 便利店收银系统_简单又好用的便利店收银系统
  9. python md5加密字符串_Python使用MD5加密字符串示例
  10. ai面试的优缺点_AI面试需要注意哪些问题?
  11. 北达科他州立大学计算机科学专业,2019上海软科世界一流学科排名计算机科学与工程专业排名北达科他州立大学排名第201-300...
  12. oem persist sysinfo三个分区的作用是什么?
  13. 计算机视觉基础理论知识
  14. 使用ADO创建Excel数据表
  15. 【论文】医疗大数据方面的资料
  16. java 错误:The public type *** must be defined in its own file***
  17. 【树形结构】巴基斯坦城市列表 (城市原始数据来自md文件)
  18. 如何快速搭建自己的云桌面和云办公服务器软件系统
  19. 51nod1355:斐波那契的最小公倍数(数论)
  20. SHAR1,获取不同,release版本SHAR1,debug版本SHAR1,导致定位失败,经纬度获取为0

热门文章

  1. 斗角钩心,七巧证勾股
  2. 2018 AI Challenger全球AI挑战赛‘眼底水肿病变区域自动分割’赛道比赛总结
  3. Unity特效学习笔记——受击爆点
  4. 如何发送入职通知语音信息?入职语音通知实现方案
  5. Android O版本 应用锁功能
  6. vuex -- mutations接收参数
  7. 简单说一下session和cookies
  8. python能代替ps吗_Photoshop入门学习之自从会了Python之后,我就没用过PS了
  9. ULAM /区块链未来将颠覆的9个行业
  10. 设计模式——简单工厂、工厂方法和抽象工厂的区别与联系