带有函数和结构指针的ctypes出错

Error in ctypes with a function and a structure pointer

本文关键字:ctypes 出错 指针 结构 函数      更新时间:2023-10-16

我试图使用c++函数(在dll中)与python。要做到这一点,我使用ctypes库。

我的c++代码是一个使用webcam的库,它可以导出一组C函数。

这是我想要使用的函数:

/*! Release the grabber object. Must be called, if the calling application
    does no longer need the grabber.
    @param hGrabber The handle to grabber to be released.
    @sa IC_CreateGrabber
*/
void AC IC_ReleaseGrabber( HGRABBER *hGrabber ); ///< Releas an HGRABBER object.

是释放记忆函数

这个HGRABBER结构:

//////////////////////////////////////////////////////////////////////////
/*! This is the handle of an grabber object. Please use the HGRABBER type to access
    this object.
*/
typedef struct HGRABBER_t__ { int unused; } HGRABBER_t; ///<Internal structure of the grabber object handle.
#define HGRABBER HGRABBER_t* ///< Type of grabber object handle. Used for all functions. 
我的代码是:

必要结构HGRABBER(在我的例子中它被命名为HGRABBER_TYPE)

class HGRABBER_T(ctypes.Structure):
    _fields_ = [("unused", ctypes.c_int)] 
HGRABBER_TYPE = ctypes.POINTER(HGRABBER_T)

call函数:

self._dllref =  ctypes.windll.LoadLibrary(DLL_PATH)
self._grabber_handle = self._dllref.IC_CreateGrabber() 
 ....
 ...
 ....
self._dllref.IC_ReleaseGrabber(ctypes.pointer(HGRABBER_TYPE(self._grabber_handle)))

,最后,我收到的错误:

self._dllref.IC_ReleaseGrabber(ctypes.byref(HGRABBER_TYPE(self._grabber_handle)))
TypeError: expected HGRABBER_T instead of int

我检查了其他相关的帖子,例如这个,但它没有帮助我…

谢谢你的帮助!

更新:

我应用了restype和argtypes来指定参数和返回值(谢谢!)。

修改后的代码为:

self._dllref =  ctypes.windll.LoadLibrary(DLL_PATH)
self._dllref.IC_CreateGrabber.restype = HGRABBER_TYPE        
self._grabber_handle = self._dllref.IC_CreateGrabber() 
...
..
self._dllref.IC_ReleaseGrabber.argtypes = [HGRABBER_TYPE]
self._dllref.IC_ReleaseGrabber(self._grabber_handle)
我应该有多个错误,现在我的错误是:
self._dllref.IC_ReleaseGrabber(self._grabber_handle)
WindowsError: exception: access violation writing 0x6E657137

我检查了函数的参数(HGRABBER * HGRABBER),释放函数的argtypes应该是:

self._dllref.IC_ReleaseGrabber.argtypes = [ctypes.POINTER(HGRABBER_TYPE)]
修改后,我得到另一个不同的错误:
self._dllref.IC_ReleaseGrabber(self._grabber_handle)
WindowsError: exception: access violation reading 0x6B0F1FE0

我正在搜索这些错误,这似乎是一个糟糕的转换指针,我不理解,结构似乎很简单,我不知道我错过了什么。

更新2

我忘了添加ctypes。当我调用函数时,它必须是:

 self._dllref.IC_ReleaseGrabber(ctypes.byref(self._grabber_handle))

更新3

不幸的是,我得到一个与指针参数((ctypes.byref(self._grabber_handle)))相关的随机错误,有时释放函数接受对象,但有时给出此错误:

    _dllref.IC_ReleaseGrabber(ctypes.byref(_grabber_handle))
WindowsError: exception: access violation reading 0x5A694F44

您可以设置IC_CreateGrabber的返回类型,以便在调用IC_ReleaseGrabber时不需要重铸。

例如:

self._dllref =  ctypes.windll.LoadLibrary(DLL_PATH)
# here set the return type
self._dllref.IC_CreateGrabber.restype = HGRABBER_TYPE
# here set the argtypes
self._dllref.IC_ReleaseGrabber.argtypes = [ctypes.POINTER(HGRABBER_TYPE)]
self._grabber_handle = self._dllref.IC_CreateGrabber() 
self._dllref.IC_ReleaseGrabber(ctypes.byref(self._grabber_handle))

通过设置库函数的restypeargtypes, ctypes知道如何处理来自C端的值。