简体   繁体   中英

is there a Python Equivalent to Memcpy

I am trying to port some C Code but I am really stuck cause of the use of memcpy I tried with ctypes (did not work). I am hoping to find a python way of using an equivalent function of memcpy

Any ideas

Here is an example of the C Code I am trying to port

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

You almost certainly don't need to call htons and then copy the 2 bytes into a buffer—see Keith's answer for why.

However, if you do need to do this (maybe you're crafting IP packets to compare to captured wire packets as a test or something?), you can.

First, if you're using a bytearray (or anything else that meets the writable buffer protocol), you just use normal list -style slice assignment:

# like C's memcpy(buf+i, foo, 2)
buf[i:i+2] = foo

You don't have that two-byte string foo ; you have a short integer. In C, you can turn that into a pointer to two bytes just by using the & operator to get its address, but Python can't do that. Fortunately, there's a standard library module called struct designed for exactly this kind of thing:

t = socket.htons(int(port))
buf[i:i+2] = struct.pack('h', t)

Or, because struct can handle endianness for you:

t = int(port)
buf[i:i+2] = struct.pack('!h', t)

However, often you don't even need the buffer copying; you can define the entire structure all at once inside struct . For example, if you're trying to pack an IP address and port into a 6-byte array, you could do this:

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)

But this is much simpler:

addrbytes = [int(part) for part in addr.split('.')]
portshort = int(port)
buf = struct.pack('!4Bh', addrbytes[0], addrbytes[1], addrbytes[2], addrbytes[3], portshort)

I've just defined a structure that's in network order, with four bytes followed by a short, and packed my data into it.

One last thing to mention: If you really want to deal with C-style variables using C-style code, the ctypes module is another option. It's made specifically for interacting with C code, so in general it's pretty low-level (and the only module in the standard library that lets you segfault your code), but it let you build some nice mid-level stuff that looks a little more like C:

class ADDRPORT(ctypes.BigEndianStructure):
    _fields_ = [("addr", ctypes.c_char*4),
                ("port", ctypes.c_short)]

addrport = ADDRPORT(addrbytes, portshort)

Since your C code is progressively filling up a buffer, rather than setting elements of a struct , this probably isn't what you want. But it's worth being aware of, because it probably will be what you want at some point.

It looks like you are trying to get a port number from user input or a string.

In Python:

port = int(port)

Then you can pass that directly to a socket instantiation:

socket = socket.socket(("127.0.0.1", port))

Python does the htons translation for you. You only need to supply an address to a socket (in the case of TCP) as a tuple of a string and integer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM