【问题标题】:Error in ctypes with a function and a structure pointer带有函数和结构指针的 ctypes 错误
【发布时间】:2014-07-15 06:41:58
【问题描述】:

我正在尝试将 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)

调用函数:

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),释放函数的参数类型应该是:

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))),有时释放函数接受对象但有时会给出此错误:

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

【问题讨论】:

  • 你不需要为HGRABBER_T定义_fields_,因为它只是用来创建不透明的指针类型。
  • 好的,我会测试没有这个fields的代码,谢谢!

标签: python c++ c ctypes


【解决方案1】:

你可以设置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 端的值。

【讨论】:

  • 这个答案是正确的,但在我看来,重要的是要指定这个答案只能解决我的部分问题。我有两个错误。我会编辑我的帖子来解释它
  • @carlos.baez 是的,这看起来是正确的。当我查看原始问题时,我错过了HGRABBER*
  • 对不起@ebarr,我以为它可以工作,但不幸的是,它随机抛出了一个指针异常exception: access violation reading 0x5A694F44....
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-16
  • 2016-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-26
相关资源
最近更新 更多