4

C プログラムから SysV::IPC 経由で Perl スクリプトに渡される unsigned long 値をアンパックしようとしています。

値が正しいことはわかっており (同じ値を 2 つのキューに送信するテストを行いました。1 つは Perl によって読み取られ、もう 1 つは C アプリケーションによって読み取られます)、先行する値はすべて正しく読み取られます ( 64 で動作するq代わりに使用されます)。 i!-ビット整数)。

PHP にも同様のバグがあったことも知られています (「unsigned long on 64 ビット マシン」を検索してください) (同様のようです: Pack / unpack a 64-bit int on 64-bit architecture in PHP )

これまでにテストされた引数:

  • ..Q ( = 予想よりも大きな値)
  • ..L ( = 0)
  • ..L! ( = 大きな値)
  • ..l (= 0)
  • ..l! ( = 大きな値)
  • ..lN! ( = 0)
  • ..ん、..ん!( = 0)

use bigint; use bignum;- 無効。

詳細:

  • sizeof(unsigned long)= 8;
  • Data::Dumper->new([$thatstring])->Useqq(1)->Dump();意味のあるものに沿って多くのヌルバイト..
  • byteorder='12345678';

解決策: - x4Q4 バイトのパディングあり。

4

2 に答える 2

3

Q64 ビット Perl を使用している場合、テンプレートで使用するアンパックはすぐに使用できます。

The TEMPLATE is a sequence of characters that give the order
and type of values, as follows:

 ...

 q   A signed quad (64-bit) value.
 Q   An unsigned quad value.
       (Quads are available only if your system supports 64-bit
        integer values _and_ if Perl has been compiled to support those.
        Causes a fatal error otherwise.)

より堅牢なソリューションとして、値を 8 バイトの文字列にアンパックし、Math::Int64モジュールを使用して整数に変換します。

use Math::Int64 qw( :native_if_available int64 );

...

$string_value = unpack("A8", $longint_from_the_C_program);

# one of these two functions will work, depending on your system's endian-ness
$int_value = Math::Int64::native_to_int64($string_value);
$int_value = Math::Int64::net_to_int64($string_value);
于 2011-03-30T15:46:45.363 に答える
1

解決策は簡単でしたx4Q。実際の値の前に 4 バイトをスキップするように追加しました。パディング/アライメントをより視覚的に考える必要があります..

于 2011-03-30T18:03:36.370 に答える