You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Cython将Python中QWidget的HWND传递给C++创建Vulkan表面

解决通过Cython将Qt的sip.voidptr类型HWND传递给C++创建Vulkan表面的问题

核心思路

Qt的QWidget.winId()返回的sip.voidptr是对底层Win32窗口句柄(HWND)的封装,不能直接在Cython中强制类型转换,必须通过SIP提供的API提取其内部指针值,再传递给C++代码。

步骤与修正代码

1. 在Cython文件中引入SIP API并正确提取指针

修改pyandcpp.pyx,添加SIP的C函数声明,用sip_api_voidptr_to_ptr获取sip.voidptr的底层指针:

# 引入SIP的API声明
cdef extern from "sip.h":
    void* sip_api_voidptr_to_ptr(object voidptr)

# 声明C++类
cdef extern from 'AppInit.hpp':
    cdef cppclass cpClass:
        cpClass(int, HWND)  # hinstance, hwnd

cdef class pyClass:
    cdef cpClass *thisptr
    def __cinit__(self, h, ptr):
        # 提取sip.voidptr的底层指针并转换为HWND
        cdef HWND hwnd = <HWND>sip_api_voidptr_to_ptr(ptr)
        self.thisptr = new cpClass(h, hwnd)
        print('Done...')

2. 修正C++代码的语法与依赖

修改cppfile.cpp,修复拼写错误、补全函数定义,并确保包含必要的头文件:

#include <windows.h>
#include <vulkan/vulkan.h>
#include <stdexcept>

// 假设instance是已初始化的Vulkan实例(全局变量或类成员)
VkInstance instance;
VkSurfaceKHR surface_;

class cpClass {
public:
    cpClass(int h, HWND ptr);
    void createSurface(int h, HWND ptr);
};

cpClass::cpClass(int h, HWND ptr) {
    createSurface(h, ptr);
}

void cpClass::createSurface(int h, HWND ptr) {
    VkWin32SurfaceCreateInfoKHR create_info = {};
    create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
    create_info.hinstance = GetModuleHandle(nullptr);
    create_info.hwnd = ptr;

    VkResult result = vkCreateWin32SurfaceKHR(instance, &create_info, nullptr, &surface_);
    if (result != VK_SUCCESS) {
        throw std::runtime_error("failed to create surface!");
    }
    // 建议用日志输出成功信息,而非抛出异常中断程序
}

3. 确保Python端传递有效句柄

Main.py中需确保窗口已完成初始化(显示后再获取winId(),避免拿到无效句柄):

from PyQt5.QtWidgets import QWidget
# 假设已导入编译后的pyClass

class HelloTriangleApplication(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        # 先显示窗口,确保生成有效HWND
        self.show()
        pyClass(0, self.winId())

关键注意事项

  • SIP版本兼容:sip_api_voidptr_to_ptr在SIP 4及以上版本可用,需保证PyQt与SIP版本匹配。
  • Vulkan扩展启用:初始化Vulkan实例时必须启用VK_KHR_win32_surface扩展,否则vkCreateWin32SurfaceKHR会调用失败。
  • 窗口生命周期:Qt窗口的winId()仅在窗口首次显示后才会生成真实的HWND,提前调用可能获取临时无效值。

内容的提问来源于stack exchange,提问作者Akshayakeerthi Duraisamy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 07:25:18