如何将C++ Widget嵌入PyQt5?求适配SIP 6的可用最小示例
适配SIP 6的C++ Qt小部件绑定PyQt最小实现示例
本示例实现C++编写的Qt自定义小部件绑定到PyQt调用,兼容SIP 6+版本,修复旧版SIP配置方法失效问题。
前置依赖
- SIP 6.x
- 对应版本的PyQt(本示例以PyQt6为例,PyQt5适配逻辑一致)
- 匹配版本的Qt开发环境
- 对应平台的C++编译器
步骤1:编写C++自定义Qt小部件
custom_widget.h 头文件
#include <QWidget> #include <QLabel> class CustomCppWidget : public QWidget { Q_OBJECT public: explicit CustomCppWidget(QWidget *parent = nullptr); void setText(const QString &text); private: QLabel *m_label; };
custom_widget.cpp 实现文件
#include "custom_widget.h" CustomCppWidget::CustomCppWidget(QWidget *parent) : QWidget(parent) { m_label = new QLabel("这是C++原生实现的Qt小部件", this); setFixedSize(300, 200); } void CustomCppWidget::setText(const QString &text) { m_label->setText(text); }
步骤2:编写SIP绑定定义文件
创建custom_widget.sip文件,定义Python可调用的接口:
%Module CustomCppWidget %Import PyQt6/QtCore/QtCoremod.sip %Import PyQt6/QtWidgets/QtWidgetsmod.sip %Include custom_widget.h class CustomCppWidget : public QWidget { %TypeHeaderCode #include "custom_widget.h" %End public: explicit CustomCppWidget(QWidget *parent /TransferThis/ = nullptr); void setText(const QString &text); };
注:/TransferThis/标记遵循Qt父子对象内存管理规则,父组件销毁时自动回收C++小部件内存。
步骤3:编写SIP 6项目配置文件
SIP 6已废弃旧版sipconfig配置方式,改用pyproject.toml做项目配置:
[project] name = "CustomCppWidget" version = "1.0.0" [tool.sip.project] sip-include-dirs = [ "替换为你环境中PyQt6的bindings目录路径", # 示例:Python/site-packages/PyQt6/bindings "替换为你环境中Qt的头文件根目录路径" # 示例:Qt/6.5.0/msvc2019_64/include ] [tool.sip.bindings.CustomCppWidget] headers = ["custom_widget.h"] libraries = ["CustomCppWidget"] library-dirs = ["."] # Windows MSVC编译器用下一行,Linux/macOS替换为 ["-std=c++17"] extra-compile-args = ["/std:c++17"]
步骤4:编译C++小部件为静态库
Windows(MSVC环境)
cl /c /std:c++17 /I Qt头文件路径 /I Qt头文件路径/QtCore /I Qt头文件路径/QtWidgets custom_widget.cpp lib /OUT:CustomCppWidget.lib custom_widget.obj
Linux
g++ -c -fPIC -std=c++17 -I Qt头文件路径 -I Qt头文件路径/QtCore -I Qt头文件路径/QtWidgets custom_widget.cpp ar rcs libCustomCppWidget.a custom_widget.o
步骤5:构建Python绑定模块
执行sip-build命令,构建完成后可在dist目录得到可直接导入的Python模块。
步骤6:PyQt调用测试
编写测试脚本test.py:
import sys from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget from CustomCppWidget import CustomCppWidget class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("SIP6绑定测试") central_widget = QWidget() layout = QVBoxLayout(central_widget) # 实例化C++实现的自定义小部件 self.cpp_widget = CustomCppWidget() layout.addWidget(self.cpp_widget) # 测试调用C++暴露的方法 btn = QPushButton("修改C++小部件文本") btn.clicked.connect(lambda: self.cpp_widget.setText("从Python触发修改的文本")) layout.addWidget(btn) self.setCentralWidget(central_widget) self.resize(400, 300) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec())
运行脚本即可看到绑定后的C小部件正常加载,按钮点击可正常调用C方法。
注意事项
- SIP版本、PyQt版本、Qt开发环境版本必须完全匹配,禁止交叉版本混用
- 所有配置中的路径需替换为你本地环境的实际路径,路径含空格需用引号包裹
- 适配PyQt5仅需将sip文件中导入的PyQt6路径修改为PyQt5对应路径,配置文件同步调整即可
内容的提问来源于stack exchange,提问作者Cerno
相关产品推荐
相关产品推荐

