如何检测PyObject的Python类型?如何获取其AttrString及代码疑问
检测PyObject的Python类型:修正你的代码并正确实现
你的代码里存在几个关键问题,导致无法正确判断PyObject是否为cv2.cuda_GpuMat类型:
PyObject_HasAttrString用法错误:你传入的"cv2.cuda_GpuMat"是类型的完整名称,不是目标对象的属性,所以这个检查永远会失败。- 指针转换逻辑错误:
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
相关产品推荐
相关产品推荐

