使用sizeof函数在cython和ctypes之间发生冲突

时间:2017-03-13 06:00:18

标签: cython ctypes

我在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)) 

1 个答案:

答案 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在编译时被评估为常量,而不是在运行时调用,因此您的使用情况更不合理。