Pybind11绑定QString::toLocal8Bit报错:无匹配函数,求解决方案
问题
在Windows 10+MSYS2环境下用Pybind11开发调用Qt5的Python扩展DLL,其他功能正常,但导出QString::toLocal8Bit时编译报no matching function for call错误;不导出该方法时,Python调用会触发AttributeError,需实现QString.toLocal8Bit在Python中的正常调用。
平台信息
Microsoft Windows [Version 10.0.19045.4355] uname -s: MINGW64_NT-10.0-19045 python3 --version: Python 3.11.9 g++ --version: g++.exe (Rev6, Built by MSYS2 project) 13.2.0 Qt: v 5.15.12 PyQt: v 5.15.10
错误原因
Qt的QString::toLocal8Bit是重载函数,存在两个版本:
QByteArray QString::toLocal8Bit() const(无参版本,即你需要的功能)QByteArray QString::toLocal8Bit(QByteArray *buffer) const(带输出参数的版本)
Pybind11无法自动推断要绑定的重载版本,因此编译时出现匹配错误。
解决方案
方案1:显式指定重载类型
通过强制类型转换明确指定绑定无参版本的toLocal8Bit,同时可额外绑定QByteArray以支持Python端的类型转换:
#include <pybind11/pybind11.h> #include <QStringList> #include <QByteArray> QString myStringTesterFunc(const QString &inString, bool specProcess) { QString ret_str = "Result: "; ret_str.append(QString("%1").arg(inString)); ret_str.append(QString("%1").arg(" - ")); ret_str.append(specProcess ? "Special" : "Regular"); return ret_str; } namespace py = pybind11; PYBIND11_MODULE(QtTestLib, m) { m.doc() = "pybind11 example module (myStringTesterFunc)"; m.def("myStringTesterFunc", &myStringTesterFunc, "A function that tests QString"); // 绑定QString类 py::class_<QString>(m, "QString") .def(py::init<const char*>()) // 显式指定无参的toLocal8Bit重载 .def("toLocal8Bit", static_cast<QByteArray (QString::*)() const>(&QString::toLocal8Bit)) ; // 绑定QByteArray,使其能在Python中转为字节或字符串 py::class_<QByteArray>(m, "QByteArray") .def("__bytes__", [](const QByteArray& ba) { return py::bytes(ba.constData(), ba.size()); }) .def("__str__", [](const QByteArray& ba) { return QString(ba).toStdString(); }) ; }
方案2:Lambda函数包装(更直观)
用Lambda直接调用无参版本,并将返回的QByteArray转为Python原生bytes类型,无需额外绑定QByteArray:
#include <pybind11/pybind11.h> #include <QStringList> #include <QByteArray> QString myStringTesterFunc(const QString &inString, bool specProcess) { QString ret_str = "Result: "; ret_str.append(QString("%1").arg(inString)); ret_str.append(QString("%1").arg(" - ")); ret_str.append(specProcess ? "Special" : "Regular"); return ret_str; } namespace py = pybind11; PYBIND11_MODULE(QtTestLib, m) { m.doc() = "pybind11 example module (myStringTesterFunc)"; m.def("myStringTesterFunc", &myStringTesterFunc, "A function that tests QString"); py::class_<QString>(m, "QString") .def(py::init<const char*>()) // Lambda包装直接返回Python字节对象 .def("toLocal8Bit", [](const QString& self) { QByteArray ba = self.toLocal8Bit(); return py::bytes(ba.constData(), ba.size()); }) ; }
编译命令优化(可选)
将原命令中直接链接Qt5Core.dll改为链接导入库,更符合编译规范:
g++ -g -Wall -Wextra -O -pedantic -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) QtTestLib.cpp -o QtTestLib$(python3-config --extension-suffix) -I/mingw64/include/QtCore -I/mingw64/include/python3.11 $(python3-config --ldflags) -lQt5Core $(python3-config --libs)
测试验证
修改后Python代码可正常运行:
import QtTestLib qstringret = QtTestLib.myStringTesterFunc(QtTestLib.QString("Hello world"), True) print(qstringret) # 方案1需转类型:print(bytes(qstringret.toLocal8Bit())) # 方案2直接输出:print(qstringret.toLocal8Bit())
内容的提问来源于stack exchange,提问作者sdbbs
相关产品推荐
相关产品推荐

