下面是我的源代码及其在Win10命令行中的输出。你知道吗
from ctypes import *
class eH():
x= c_uint(0)
print (type(x) == c_uint)
print (type(eH.x) == c_uint)
print (eH.x)
print (type(eH.x))
print (type(eH.x) == c_ulong)
print (c_uint == c_ulong)
print (c_int == c_long)
print ("\nEnd of eH prints\n#####")
class eHardware(Structure):
_fields_= [("xyz", c_uint)]
a= eHardware()
a.xyz= eH.x
print (a.xyz)
print (a.xyz == eH.x)
print (type(a.xyz))
print (type(c_uint(a.xyz)))
命令行输出位于链接:https://pastebin.com/umWUDEuy
我注意到的第一件事是c\u uint==c\u ulong输出True。这是否意味着ctypes动态地分配类型,并在内存中将它们视为相同的类型?如果我想将类似的脚本移植到一种类型敏感的语言,比如C语言,这种设计会有什么意义吗
第二,在第17行中,我指定a.xyz=eH.x,但在第19行中,a.xyz==eH.x的计算结果为False。另外,a.xyz的类型被转换为int,而eH.x的类型是c_uint(或c_ulong,因为它在调用type()时总是计算为) 提前感谢您的回复。你知道吗
这在the docs的顶部解释:
如果您想知道它为什么这样做,那么它是为了改进与C代码的交互。你知道吗
C是一种弱类型语言
int
和long
总是不同的类型,但是您可以通过复杂的整数提升和缩小规则在它们之间隐式地进行强制转换。1在许多平台上,int
和long
恰好都是32位的,因此这些规则并不重要,但在其他平台上,long
是64位的,2他们就是这样做的。这使得编写在你的机器上运行的代码变得非常容易,但是通过破坏堆栈(甚至可能以攻击者可以利用的方式)在其他人的机器上产生错误。你知道吗ctypes
试图通过明确定义c_int
是c_long
的别名来控制这一点,当且仅当它们的大小相同时。所以:int
时总是小心地使用c_int
,在它需要long
时总是使用c_long
,那么您的代码将是可移植的,就像在C中一样ctypes
得到一个异常,而不是segfault。你知道吗我想这取决于你所说的“在飞”是什么意思。如果您查看the source,您将看到在编译模块时,它会执行以下操作:
当然,通常情况下,当你
import ctypes
时,你会得到一个预编译的ctypes.pyc
文件,3所以c_int
的定义会以某种方式冻结到pyc
。所以,在这个意义上,你不必担心它是动态的。但是您可以删除.pyc
文件,或者告诉Python不要使用它们。如果你真的想,你甚至可以把monkeypatchctypes.c_int
变成别的东西。所以,从这个意义上说,如果你想它是动态的,它肯定是动态的好吧,整个设计的重点是尽可能地匹配C(尤其是,用于构建CPython解释器的C编译器的实现定义的细节),同时解决一些与C打交道的陷阱,很少用
ctypes
设计接口,然后用C实现它;通常情况下是相反的。但偶尔也会发生这种情况(通常与映射到numpy数组的多处理共享内存有关……)。你知道吗在这种情况下,只需遵循相同的规则:确保在Python代码中保持
c_int
和c_long
,并将它们与C代码中的int
和long
相匹配,这样就可以了。您肯定希望在C编译器中启用(并读取)警告,以便在将它们混合在一起时尝试捕获它们。在调试过程中,要为偶尔出现的segfaults或内存损坏做好准备,但在C中,您始终需要做好准备。5当您访问结构成员、将参数传递到C函数和返回值等时,转换为本机类型是相当复杂的。95%的时候它只是做你想做的,最好不要担心。你知道吗
当你第一次点击另外5%的时候(通常是因为你有一个
c_char_p
你想把它当作一个指针而不是一个字符串……),没有什么可以替代阅读文档和学习默认转换和_as_parameter_
和_CData
类和restype
与errcheck
等等。在交互式口译员中做一些实验,也许可以阅读源代码。61。大多数现代编译器都会对缩小转换范围发出警告,甚至允许您有选择地将其转换为错误。
2。在过去,当
ctypes
首次被设计时,它更常见于int
为16位,但效果相同。3。如果您使用Windows或macpython安装程序,或者RPM或DEB二进制软件包,或者系统中预装的Python,那么stdlib几乎总是在构建二进制软件包时在其他机器上编译的。如果您是从源代码构建的,它通常是在您的计算机上构建或安装时编译的。如果没有,它通常在您第一次
import ctypes
时被编译。4。虽然我不知道你为什么要这样。用不同的名称定义自己的类型更容易…
5。您可能想考虑使用静态类型和C兼容的语言,但它比C更像是一个更严格和更强大的类型系统,比如RIST,或者至少C++或D.,那么编译器可以做更多的事情来帮助您确定事情的进展。但是这里的折衷和在C语言和另一种语言之间进行选择时的折衷是一样的;这里没有任何特定的东西。
6。最后把你的手举在空中,宣布从现在起你只会使用
cffi
而不是ctypes
,这一直持续到你第一次遇到cffi
的怪癖…相关问题 更多 >
编程相关推荐