Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

246
Vistas
Uso de enteros de 64 bits con Perl XS

Quiero portar una función C usando enteros de 64 bits al código Perl. Para hacer eso, uso Perl XS.

Mi problema es que no hay enteros de 64 bits en los tipos Perl XS (solo U32, U16 y U8).

Entonces, ¿cuál es la mejor manera de usar números enteros de 64 bits en código Perl XS?

Aquí hay un ejemplo de código de lo que quiero hacer:

 uint64_t foo(integer) uint64_t integer CODE: RETVAL = foo(integer); OUTPUT: RETVAL

foo() tiene el prototipo C:

 uint64_t foo(uint64_t);

No encontré nada útil en la documentación de perlxs y en stackoverflow.com.

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

El tipo interno de Perl para enteros sin signo es UV . Si su plataforma tiene UV de 64 bits, debería estar bien.

Con UV de 32 bits (SO de 32 bits y Perl se compiló sin use64bitint), puede convertir números enteros grandes hacia y desde números de coma flotante ( NV , que generalmente es un double ). Pero dado que los dobles IEEE solo tienen 53 bits de mantisa, esto provocará una pérdida de precisión para números grandes.

 uint64_t integer; // Convert uint64_t to SV. if (integer <= UV_MAX) { RETVAL = newSVuv((UV)integer); } else { RETVAL = newSVnv((NV)integer); } // Convert SV to uint64_t with range checks. if (SvUOK(sv)) { integer = (uint64_t)SvUV(sv); } else if (SvIOK(sv)) { IV iv = SvIV(sv); if (iv < 0) croak(...); integer = (uint64_t)iv; } else if (SvNOK(sv)) { NV nv = SvNV(sv); if (nv < 0.0 || nv >= 18446744073709551616.0) croak(...); integer = (uint64_t)nv; } else { // Parse a uint64_t from the string value, or whatever. }

Si no puede vivir con la pérdida de precisión y desea admitir UV de 32 bits, puede usar la API C de Math::Int64 (consulte también Module::CAPIMaker ):

 #define MATH_INT64_NATIVE_IF_AVAILABLE #include "perl_math_int64.h" MODULE = ... BOOT: PERL_MATH_INT64_LOAD_OR_CROAK; SV* foo(args...) CODE: uint64_t integer = ... RETVAL = newSVu64(integer); OUTPUT: RETVAL

Con un mapa tipográfico como

 TYPEMAP uint64_t T_UINT64 INPUT T_UINT64 $var = SvU64($arg) OUTPUT T_UINT64 $arg = newSVu64($var);

puedes usar uint64_t directamente en tu XS:

 uint64_t foo(arg) uint64_t arg
over 4 years ago · Santiago Trujillo Denunciar

0

El tipo uint64_t no está definido en el typemap de tipos predeterminado, que viene con la distribución de Perl. Según perlxstypemap :

En términos más prácticos, el mapa de tipos es una colección de fragmentos de código que utiliza el compilador xsubpp para asignar parámetros y valores de funciones de C a valores de Perl.

Puede definir su propio mapa de tipos (en el mismo directorio que .xs typemap . Podría verse como:

 TYPEMAP unsigned long long T_U_LONG_LONG uint64_t T_U_LONG_LONG # equivalent to typedef unsigned long long uint64_t; INPUT T_U_LONG_LONG $var = (unsigned long long)SvUV($arg) OUTPUT T_U_LONG_LONG sv_setuv($arg, (UV)$var);

No estoy seguro acerca de estas asignaciones, especialmente SvUV y parte UV , por lo que debe probarlo cuidadosamente en cualquier código real. Sospecho que son solo números enteros "simples", por lo que uint64_t es completamente funcional solo para uso interno, es decir, dentro de la definición de la función.

Tenga en cuenta que el tipo unsigned long long tiene al menos 64 bits de ancho según el estándar C (desde C99), pero es de 64 bits en todas las implementaciones que conozco.

Con test.xs como:

 #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" MODULE = test PACKAGE = test unsigned int u64_mul_high(a, b) unsigned int a unsigned int b CODE: RETVAL = ((uint64_t) a * b) >> 32; OUTPUT: RETVAL

y test.pl definido como:

 #!/usr/bin/perl use ExtUtils::testlib; use test; print test::u64_mul_high(2147483647, 1000), "\n";

obtienes un resultado de:

 499 (0001 1111 0011)

que es el miembro superior de 32 bits de una multiplicación de 32-bit x 32-bit que da como resultado un entero de 64 bits.

Verifiqué esto en GNU/Linux de 32 bits con sizeof(long) = 4 y Perl 5.10.

over 4 years ago · Santiago Trujillo Denunciar

0

$ perl -MConfig -le 'print $Config{use64bitint}'

mostrará si su perl fue compilado para usar números enteros de 64 bits. Si es así, IV es de 64 bits.

Véase también perldoc perlguts :

¿Qué es un "IV"?

Perl utiliza un typedef IV especial que es un tipo de entero con signo simple que se garantiza que es lo suficientemente grande como para contener un puntero (así como un número entero). Además, está el UV, que es simplemente un IV sin firmar.

Perl también utiliza dos definiciones de tipos especiales, I32 e I16, que siempre tendrán una longitud mínima de 32 y 16 bits, respectivamente. (Nuevamente, también hay U32 y U16). Por lo general, tendrán exactamente 32 y 16 bits de largo, pero en Crays ambos serán de 64 bits.

Véase también Matemáticas::Int64 :

Este módulo agrega soporte para enteros de 64 bits, con y sin signo, a Perl.

...

Respaldo al soporte nativo de 64 bits si está disponible

Si el pragma léxico Math::Int64::native_if_available se usa en su programa y la versión de Perl en uso tiene soporte nativo para enteros de 64 bits, las funciones importadas del módulo que crean enteros de 64 bits (es decir, uint64 , int64 , string_to_int64 , native_to_int64 , etc.) devolverá escalares perl regulares.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda