我正在尝试使用python的C ++函数(在dll中)。为此,我使用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)
通话功能:
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
我检查了其他相关帖子,例如this,但它对我没有帮助..
我感谢任何帮助!
更新
我应用了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.byref,它必须是:
self._dllref.IC_ReleaseGrabber(ctypes.byref(self._grabber_handle))
更新3
不幸的是,我收到与指针参数((ctypes.byref(self._grabber_handle))
)相关的随机错误,有时release函数会接受该对象,但有时会出现此错误:
_dllref.IC_ReleaseGrabber(ctypes.byref(_grabber_handle))
WindowsError: exception: access violation reading 0x5A694F44
答案 0 :(得分:2)
您可以设置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))
通过设置库函数的restype
和argtypes
,ctypes知道如何处理C方面的值。