私はいくつかの C コードを移植しようとしていますが、ctypes で試した memcpy の使用が原因で本当に行き詰まっています (動作しませんでした)。memcpy の同等の機能を使用する Python の方法を見つけたいと思っています。
何か案は
これは私が移植しようとしているCコードの例です
i = l + 5;
t = htons(atoi(port));
memcpy((buf+i), &t, 2);
ほぼ確実に、2バイトを呼び出してからバッファにコピーする必要はありませんhtons
。理由については、Keithの回答を参照してください。
ただし、これを行う必要がある場合(おそらく、テストなどとしてキャプチャされたワイヤパケットと比較するためにIPパケットを作成しているのでしょうか?)、可能です。
まず、bytearray
(または書き込み可能なバッファプロトコルを満たす他のもの)を使用している場合は、通常のlist
スタイルのスライス割り当てを使用します。
# like C's memcpy(buf+i, foo, 2)
buf[i:i+2] = foo
その2バイトの文字列はありませんfoo
; あなたは短整数を持っています。Cでは、演算子を使用してアドレスを取得するだけで、これを2バイトへのポインターに変換できます&
が、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)
ネットワークの順序で、4バイトの後に短い構造が続く構造を定義し、データをその構造にパックしました。
最後に言及すべきことは、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
、これはおそらくあなたが望むものではありません。しかし、それはおそらくいつかあなたが望むものになるので、知っておく価値があります。
ユーザー入力または文字列からポート番号を取得しようとしているようです。
Python の場合:
port = int(port)
次に、それをソケットのインスタンス化に直接渡すことができます。
socket = socket.socket(("127.0.0.1", port))
Python がhtons
翻訳を行います。ソケット (TCP の場合) にアドレスを文字列と整数のタプルとして指定するだけで済みます。