4 Stimmen

Wie entpackt man (64-bit) unsigned long in 64-bit Perl?

Ich versuche, einen vorzeichenlosen Long-Wert zu entpacken, der von einem C-Programm an ein Perl-Skript über SysV::IPC übergeben wird.

Es ist bekannt, dass der Wert korrekt ist (ich habe einen Test durchgeführt, bei dem derselbe Wert in zwei Warteschlangen gesendet wird, wobei eine von Perl und die zweite von der C-Anwendung gelesen wird), und alle vordefinierten Werte werden korrekt gelesen (mit q anstelle von i! um mit 64-Bit-Ganzzahlen zu arbeiten).

Es ist auch bekannt, dass PHP etwas Ähnliches in bugs (Suche nach "unsigned long on 64 bit machines") (scheint ähnlich zu sein: Packen/Entpacken eines 64-Bit-Int auf einer 64-Bit-Architektur in PHP )

Bisher getestete Argumente:

  • ..Q ( = ein Wert, der größer ist als erwartet)
  • ..L ( = 0)
  • ..L! ( = großer Wert)
  • ..l ( = 0)
  • ..l! ( = großer Wert)
  • ..lN! ( = 0)
  • ..N, ..N! ( = 0)

use bigint; use bignum; -- keine Wirkung.

Einzelheiten:

  • sizeof(unsigned long) = 8;
  • Data::Dumper->new([$thatstring])->Useqq(1)->Dump(); eine Menge Null-Bytes entlang einiger sinnvoller
  • byteorder='12345678';

S - x4Q mit einer Auffüllung von vier Bytes.

3voto

mob Punkte 113680

Auspacken mit Q in die Vorlage funktioniert sofort, wenn Sie 64-Bit-Perl haben:

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.)

Für eine robustere Lösung entpacken Sie den Wert in eine 8-Byte-Zeichenkette und verwenden die Math::Int64 Modul, um sie in eine Ganzzahl zu konvertieren:

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);

1voto

kagali-san Punkte 2814

Die Lösung war einfach: Hinzufügen von x4Q vier Bytes vor dem eigentlichen Wert zu überspringen; man muss sich mehr Gedanken über Einfügung/Ausrichtung machen

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X