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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With