こまった
pythonで値をバイナリにまとめて外部に送信する時に、符号付きの整数(unsigned short)と符号なし整数(signed short)をまぜる必要が出てきました。
前提として、pythonの値は型を持たないという特徴があり、そこが悩みどころです。
C+であれば型の情報を持っているので共用体unionを使えば簡単に解決しますし、またpythonでもデータを取り出す分には、struct.unpackで型の指定を分けて配列を作れば大丈夫です。
pythonで型やバイナリを扱う際にも、numpyを使えばなんとかなります。
ただデータをバイナリに入れる際に、pythonは補数がどこにあるのかよくわからず、変換で少し悩みます。
何か方法がありそうですが、調べ方がわかりません。
方法
スマートな方法が浮かばないので、ゴリ押しでやってしまいます。
python環境での値A → バイナリ配列 → C+環境のunsignedで取り出した時に値Aとなる
としたいわけです。
変換せずに実行すると、1~32767までの整数は問題ないのですが、32768以降はunsignedで取り出した時に負の数値と解釈されてしまいます。
改めて、sined short と unsigned shortの対応を見てみます。
unsigned short | signed short |
---|---|
0 | 0 |
1 | 1 |
2 | 2 |
... | ... |
32766 | 32766 |
32767 | 32767 |
32768 | -32768 |
32769 | -32767 |
32770 | -32766 |
... | ... |
65533 | -3 |
65534 | -2 |
65535 | -1 |
これを綺麗に変換できる方法がよくわからないので、
unsigned shortとして取り出した時に目的の値Aに見えるように、バイナリに入れる時に値を変換しておくようにします。
Aが元の値(0~65535)、yがsigned short(-32768~32767)として
if A > 32767:
y = -(65536 - A)
else:
y =A
と変換してyをsigned short送信すれば、先方でそのバイナリをunsined shortとして取り出した時に、元の値Aを復元できるようなります。のはずです。
これでうごくけど、なんとなく本当にこれでいいのかというモヤモヤは残ります。