我在some.py文件中定义了一个类SomeClass(ctypes.Structure),并将其导入some.pyx文件中,如下所示:
from ctypes import memset, addressof, sizeof
from some import SomeClass
someInstance = SomeClass()
memset(addressof(someInstance), 0, sizeof(SomeClass))
但是无论SomeClass中有多少个字段,sizeof函数总是返回8。 我认为sizeof函数是cython中的内置函数,而不是ctypes的函数。如果我像这样导入它,SomeClass的大小是正确的:
from ctypes import memset, addressof, sizeof as csizeof
memset(addressof(someInstance), 0, csizeof(SomeClass))
答案 0 :(得分:1)
您看到的行为与调用cdef
函数的行为一致,是Cython唯一明智的做法。
与C交互时(例如调用外部模块并调用cdef
函数)Cython决定在编译时调用哪个函数:
cdef a():
print("Hi")
from some_module import a
a() # will print Hi - this is decided by the functions Cython knows about when it compiles
import
语句在运行时进行评估。 Cython在编译时无法知道它们,因为它们定义的变量可以随意重新分配。
from some_module import a_function
del globals()['a_{}'.format('func')+'tion']
a_function() # no longer defined here, but how can Cython know?
如果Cython尝试计算cdef
函数被globals
中的某些东西覆盖(即已导入的东西),那么你将失去Cython的大部分速度增益 - 否则快速的纯C代码需要相当昂贵的字典查找:
cdef char* a = <char>malloc(sizeof(char))
会被翻译成无意义的内容,如
# pseudocode!
try:
char_tmp = globals()['char']
except KeyError:
char_tmp = built_in_char
try:
sizeof_tmp = globals()['sizeof']
except KeyError:
sizeof_tmp = built_in_sizeof
try:
malloc_tmp = globals()['malloc']
except KeyError:
malloc_tmp = built_in_malloc
a = <char>malloc_tmp(sizeof_tmp(char_tmp))
此外,这个简单的语句不能用于多线程代码,因为它现在依赖于Python解释器,它只能一次运行一个线程。
因此,唯一没有完全破坏Cython的解决方案是在编译时选择使用C sizeof
,并且无法通过导入来覆盖它。
额外注意:在实践中,C sizeof
在编译时被评估为常量,而不是在运行时调用,因此您的使用情况更不合理。