在我的 Django 应用程序(Django 1.6.0,运行在 Red Hat 上的 Python 2.7.5)中,我的数据库驱动程序看到来自 ctypes 的错误:
TypeError: incompatible types, LP_c_int instance 而不是 LP_c_int instance
代码如下所示:
is_null = value is None
param.value.is_null = pointer(c_int(is_null)) <-- error occurs on this line
我不是很熟悉ctypes(我继承了这段代码)但从表面上看,这个错误信息没有意义。该代码已经运行多年,但我现在到处都看到这个错误。我做错了什么吗?
感谢 Ilja Everilä 的评论,这是一个最小的复制:
from ctypes import *
from ctypes import _reset_cache
class DataValue(Structure):
"""Must match a_sqlany_data_value."""
_fields_ = [("buffer", POINTER(c_char)),
("buffer_size", c_size_t),
("length", POINTER(c_size_t)),
("type", c_int),
("is_null", POINTER(c_int))]
d = DataValue()
_reset_cache()
is_null = False
d.is_null = pointer( c_int( is_null ) )
我遇到了类似的问题,在我的例子中,它与预定义空的
Structure
s 来绕过循环引用有关。我在做这样的事情:
from ctypes import Structure, POINTER, pointer, c_int
class B(Structure):
pass
class A(Structure):
_fields_ = (('b_ref', POINTER(B)),)
class B(Structure):
_fields_ = (('a_ref', POINTER(A)),)
b = B()
a = A()
a.b_ref = pointer(b)
b.a_ref = pointer(a)
给出结果:
TypeError: incompatible types, LP_B instance instead of LP_B instance
多么无用的信息...🤬
评论让我知道 ctypes 缓存的存在,这让我意识到重新定义是问题所在。解决方案是在设置之前简单地预定义所有类
_fields_
:
from ctypes import Structure, POINTER, pointer, c_int
class A(Structure): pass
class B(Structure): pass
A._fields_ = (('b_ref', POINTER(B)),)
B._fields_ = (('a_ref', POINTER(A)),)
b = B()
a = A()
a.b_ref = pointer(b)
b.a_ref = pointer(a)
然而,关于您与本机
c_int
的确切问题,我相信这可能与 Django 的开发服务器重新加载任何更改的模块的能力有关。然而,我从未使用过 django,我很难测试它(尤其是考虑到帖子的年龄)。 ctypes
在导入时自动调用 _reset_cache()
。通常重复调用 import ...
只会得到库的缓存版本,所以我认为它一定与某种 importlib.reload(...)
类似的调用有关。