我正在尝试移植一些C代码,但我真的卡住了,因为我尝试使用memcpy与ctypes(不工作)。我希望找到一个python的方式使用等效的memcpy函数有什么想法吗下面是我尝试移植的C代码的一个示例
i = l + 5; t = htons(atoi(port)); memcpy((buf+i), &t, 2);
sigwle7e1#
几乎可以肯定,您不需要调用htons,然后将这2个字节复制到缓冲区中a-请参阅基思的回答。然而,如果您确实需要这样做(也许您正在制作IP数据包,以与捕获的有线数据包进行比较,作为测试或其他什么?),您可以这样做。首先,如果使用bytearray(或其他任何满足可写缓冲区协议的对象),只需使用普通的list样式的切片赋值:
htons
bytearray
list
# like C's memcpy(buf+i, foo, 2) buf[i:i+2] = foo
你没有两个字节的字符串foo你有一个短整型,在C语言中,你可以把它变成一个指向两个字节的指针,只需要用&操作符来得到它的地址,但是Python不能这么做,幸运的是,有一个标准的库模块struct就是为这种事情设计的:
foo
&
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)
我刚刚定义了一个网络顺序的结构,四个字节后跟一个short,并将数据打包到其中。最后一点要提的是:如果你真的想用C风格的代码来处理C风格的变量,ctypes模块是另一个选择,它是专门为与C代码交互而设计的,所以一般来说它是相当低级的(也是标准库中唯一一个允许你对代码进行segfault的模块),但是它可以让你构建一些看起来更像C的中级东西:
class ADDRPORT(ctypes.BigEndianStructure): _fields_ = [("addr", ctypes.c_char*4), ("port", ctypes.c_short)] addrport = ADDRPORT(addrbytes, portshort)
由于C代码是逐渐填充缓冲区的,而不是设置struct的元素,这可能不是您想要的,但值得注意,因为这可能是您在某个时候想要的。
x4shl7ld2#
看起来您正在尝试从用户输入或字符串获取端口号。在Python中:
port = int(port)
然后可以将其直接传递给套接字示例化:
socket = socket.socket(("127.0.0.1", port))
Python会为你做htons的转换,你只需要提供一个套接字的地址(在TCP的情况下),作为一个字符串和整数的元组。
2条答案
按热度按时间sigwle7e1#
几乎可以肯定,您不需要调用
htons
,然后将这2个字节复制到缓冲区中a-请参阅基思的回答。然而,如果您确实需要这样做(也许您正在制作IP数据包,以与捕获的有线数据包进行比较,作为测试或其他什么?),您可以这样做。
首先,如果使用
bytearray
(或其他任何满足可写缓冲区协议的对象),只需使用普通的list
样式的切片赋值:你没有两个字节的字符串
foo
你有一个短整型,在C语言中,你可以把它变成一个指向两个字节的指针,只需要用&
操作符来得到它的地址,但是Python不能这么做,幸运的是,有一个标准的库模块struct
就是为这种事情设计的:或者,因为
struct
可以为您处理字节序:然而,通常您甚至不需要缓冲区复制;你可以在
struct
中一次定义整个结构。例如,如果你想把一个IP地址和端口打包成一个6字节的数组,你可以这样做:但这要简单得多:
我刚刚定义了一个网络顺序的结构,四个字节后跟一个short,并将数据打包到其中。
最后一点要提的是:如果你真的想用C风格的代码来处理C风格的变量,ctypes模块是另一个选择,它是专门为与C代码交互而设计的,所以一般来说它是相当低级的(也是标准库中唯一一个允许你对代码进行segfault的模块),但是它可以让你构建一些看起来更像C的中级东西:
由于C代码是逐渐填充缓冲区的,而不是设置
struct
的元素,这可能不是您想要的,但值得注意,因为这可能是您在某个时候想要的。x4shl7ld2#
看起来您正在尝试从用户输入或字符串获取端口号。
在Python中:
然后可以将其直接传递给套接字示例化:
Python会为你做
htons
的转换,你只需要提供一个套接字的地址(在TCP的情况下),作为一个字符串和整数的元组。