我想使用64位整数将一个C函数移植到Perl代码.为此,我使用Perl XS.
我的问题是Perl XS类型中没有64位整数(只有U32,U16和U8).
那么,在Perl XS代码中使用64位整数的最佳方法是什么?
这是我想要做的代码示例:
uint64_t foo(integer) uint64_t integer CODE: RETVAL = foo(integer); OUTPUT: RETVAL
foo()有C原型:
uint64_t foo(uint64_t);
我没有在perlxs文档和stackoverflow.com中找到任何有用的东西.
解决方法
uint64_t类型未在默认类型映射中定义,它与Perl分发一起提供.根据
perlxstypemap
:
In more practical terms,the typemap is a collection of code fragments
which are used by thexsubpp
compiler to map C function parameters and
values to Perl values.
您可以定义自己的类型映射(与.xs文件位于同一目录中).它可能看起来像:
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);
我不确定这些映射,尤其是SvUV和UV部分,因此您需要在任何实际代码中仔细测试它.我怀疑它们只是“普通”整数,因此uint64_t仅在内部使用时完全起作用,这在函数的定义中.
请注意,根据C标准(从C99开始),无符号long long类型至少为64位宽,但在我知道的每个实现上它都是64位.
使用test.xs:
#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
和test.pl定义为:
#!/usr/bin/perl use ExtUtils::testlib; use test; print test::u64_mul_high(2147483647,1000),"\n";
你得到的结果是:
499 (0001 1111 0011)
这是32位x 32位乘法的32位高,导致64位整数.
我在32位GNU / Linux上检查了这个,其中sizeof(long)= 4和Perl 5.10.