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

如何检测PyObject的Python类型?如何获取其AttrString及代码疑问

检测PyObject的Python类型:修正你的代码并正确实现

你的代码里存在几个关键问题,导致无法正确判断PyObject是否为cv2.cuda_GpuMat类型:

  1. PyObject_HasAttrString用法错误:你传入的"cv2.cuda_GpuMat"是类型的完整名称,不是目标对象的属性,所以这个检查永远会失败。
  2. 指针转换逻辑错误:cv2.cuda_GpuMat对象不会把内部指针以长整型属性的形式暴露,PyLong_AsVoidPtr完全不适用这里。

下面是几种正确的实现方式,按推荐度排序:

方法1:用pybind11内置的类型检查(最简洁)

既然你已经在使用pybind11,直接用py::isinstance或者获取类型对象后比较是最方便的:

#include <pybind11/pybind11.h>
#include <opencv2/cudaimgproc.hpp>

namespace py = pybind11;

int modify(cv::cuda::GpuMat* cVal, py::object &pobj)
{
    // 1. 获取cv2.cuda_GpuMat的类型对象
    py::object cuda_gpu_mat_type = py::module_::import("cv2").attr("cuda_GpuMat");
    
    // 2. 检查pobj是否是该类型的实例
    if (!py::isinstance(pobj, cuda_gpu_mat_type)) {
        return 0;
    }

    // 3. 将py::object转换为cv::cuda::GpuMat*
    // opencv-python用PyCapsule存储C++对象指针
    PyObject* ptr = pobj.ptr();
    cv::cuda::GpuMat* pyVal = (cv::cuda::GpuMat*)PyCapsule_GetPointer(ptr, "cv::cuda::GpuMat");
    
    if (pyVal) {
        *pyVal = *cVal; // 现在赋值逻辑有效
        return 1;
    }
    return 0;
}

方法2:用Python C API直接比较类型

如果不想依赖pybind11的高阶API,直接用C API实现:

#include <Python.h>
#include <opencv2/cudaimgproc.hpp>

int modify(cv::cuda::GpuMat* cVal, py::object &pobj)
{
    PyObject* pobject = pobj.ptr();
    
    // 1. 获取cv2模块和cuda_GpuMat类型
    PyObject* cv2_module = PyImport_ImportModule("cv2");
    if (!cv2_module) {
        PyErr_Clear(); // 清除导入错误
        return 0;
    }
    PyObject* cuda_gpu_mat_type = PyObject_GetAttrString(cv2_module, "cuda_GpuMat");
    Py_DECREF(cv2_module); // 释放模块引用
    
    if (!cuda_gpu_mat_type) {
        PyErr_Clear();
        return 0;
    }

    // 2. 检查对象类型是否匹配
    int is_instance = PyObject_IsInstance(pobject, cuda_gpu_mat_type);
    Py_DECREF(cuda_gpu_mat_type);
    
    if (is_instance != 1) {
        return 0;
    }

    // 3. 提取内部指针
    cv::cuda::GpuMat* pyVal = (cv::cuda::GpuMat*)PyCapsule_GetPointer(pobject, "cv::cuda::GpuMat");
    if (pyVal) {
        *pyVal = *cVal;
        return 1;
    }
    return 0;
}

关键注意事项

  • 不要用类型名称字符串判断:比如检查__name__属性是否为"cuda_GpuMat",这种方式不可靠,子类或其他同名类型会干扰判断。
  • PyCapsule的使用:opencv-python绑定中,C++对象指针通过PyCapsule存储,必须用PyCapsule_GetPointer提取,且要指定正确的名称"cv::cuda::GpuMat"。
  • 引用计数管理:使用Python C API时,记得手动释放PyObject*的引用(比如Py_DECREF),避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 19:15:35