有没有Python等效的Memcpy函数?

5

我正在尝试移植一些C代码,但由于使用了memcpy函数,我真的卡住了。我尝试使用ctypes(但失败了)。我希望能找到一种Python方式来使用memcpy的等效函数。

有什么想法吗?

这里是我正在尝试移植的C代码示例:

i = l + 5;
t = htons(atoi(port));
memcpy((buf+i), &t, 2);

7
你实际上想要达到什么目的?请展示你的Python代码。 - Marcin
5
这似乎是与套接字相关的代码。Python的socket库可以为您完成许多这方面的工作,因此在Python代码中不必担心使用htons()等函数。因此,如果没有看到更多C代码,很难说清楚。 - Greg Hewgill
11
很少有情况需要进行逐行直接编码转换。这样效率低下,并且无法充分利用新语言的优势。 - Donnie
1
我想问一下 @marcin 是什么 - 你究竟是想做什么...比如说,最终目标是什么? - Jon Clements
2个回答

7
你几乎肯定不需要调用htons,然后将2个字节复制到缓冲区中 - 请参阅Keith的答案以了解原因。
但是,如果你确实需要这样做(也许你正在构造IP数据包以与捕获的线路数据包进行比较作为测试之类的东西?),那么你可以这样做。
首先,如果你使用bytearray(或任何符合可写缓冲区协议的内容),则只需使用普通的list样式切片赋值即可。
# like C's memcpy(buf+i, foo, 2)
buf[i:i+2] = foo

你没有那个双字节字符串foo,而是有一个短整数。在C中,你可以通过使用&运算符获取其地址将其转换为两个字节的指针,但Python不能这样做。幸运的是,有一个标准库模块叫做struct专门用于这种情况:
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的元素,因此这可能不是您想要的。但是,值得注意的是,因为在某些时候这可能是您想要的。


6

看起来你正在尝试从用户输入或字符串中获取端口号。

在Python中:

port = int(port)

然后你可以直接将它传递给一个套接字实例化:
socket = socket.socket(("127.0.0.1", port))

Python会为您完成htons转换。在TCP的情况下,您只需要提供一个由字符串和整数组成的元组作为套接字的地址。


1
除非他尝试着编写原始IP数据包而不是仅仅创建套接字,否则这就是正确的答案。 - abarnert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接