我试图移植一些c代码,但我真的被困在memcpy的使用上了,我尝试了cTypes(没有工作)。我希望找到一种python方法来使用memcpy的等效函数
有什么想法吗
下面是我要移植的C代码的一个例子
i = l + 5;
t = htons(atoi(port));
memcpy((buf+i), &t, 2);
最佳答案
您几乎肯定不需要调用htons
,然后将2个字节复制到缓冲区中,请参阅keith的答案。
但是,如果你真的需要这样做(也许你正在制作IP包,以便与作为测试或其他东西捕获的有线包进行比较?),你可以。
首先,如果您使用的是bytearray
(或者符合可写缓冲协议的任何其他内容),您只需使用正常的list
样式的片断赋值:
# like C's memcpy(buf+i, foo, 2)
buf[i:i+2] = foo
你没有两个字节的字符串;你有一个短整数。在c语言中,只需使用
foo
操作符获取地址,就可以将其转换为指向两个字节的指针,但python不能这样做。幸运的是,有一个名为&
的标准库模块正是为这种情况而设计的:t = socket.htons(int(port))
buf[i:i+2] = struct.pack('h', t)
或者,因为
struct
可以处理你的后遗症:t = int(port)
buf[i:i+2] = struct.pack('!h', t)
然而,通常您甚至不需要缓冲区复制;您可以在
struct
中一次定义整个结构。例如,如果要将IP地址和端口打包到6字节数组中,可以执行以下操作:buf = bytearray(6)
i = 0
addrbytes = [int(part) for part in addr.split('.')]
buf[i:i+4] = struct.pack('4B', addrbytes[0], addrbytes[1], addrbytes[2], addrbytes[3])
i += 4
portshort = int(port)
buf[i:i+2] = struct.pack('!h', portshort)
但这要简单得多:
addrbytes = [int(part) for part in addr.split('.')]
portshort = int(port)
buf = struct.pack('!4Bh', addrbytes[0], addrbytes[1], addrbytes[2], addrbytes[3], portshort)
我刚刚定义了一个按网络顺序排列的结构,四个字节后跟一个短字节,并将数据打包到其中。
最后要提的是:如果您真的想使用c样式代码处理c样式的变量,那么ctypes模块是另一个选项。它是专门用来与C代码交互的,所以一般来说它是很低的级别(也是标准库中唯一允许你对代码进行分段)的模块,但是它可以让你构建一些看起来更像C的中等水平的东西:
class ADDRPORT(ctypes.BigEndianStructure):
_fields_ = [("addr", ctypes.c_char*4),
("port", ctypes.c_short)]
addrport = ADDRPORT(addrbytes, portshort)
由于您的c代码正在逐步填充缓冲区,而不是设置
struct
的元素,所以这可能不是您想要的。但这是值得注意的,因为它可能会是你在某个时候想要的。