如何获得一个UInt64的价值,只有toString的方法? [英] How to get value of a UInt64, toString only way?

查看:255
本文介绍了如何获得一个UInt64的价值,只有toString的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个:
ctypes.UInt64(7)



返回这个:

$ p $ var chars = SendMessage(hToolbar,TB_GETBUTTONTEXTW,local_tbb.idCommand,ctypes.voidptr_t(0));

所以

  console.log('chars =',chars,chars.toString(),uneval(chars)); 

给出

   

所以我可以通过去 chars.toString()来获取值,但是我必须运行一个 parseInt chars.UInt64

解决方案

64位整数在js-ctypes中是Javascript缺乏兼容的类型。所有的Javascript编号都是IEEE双精度浮点数( double ),这些可以表示 53位整数。所以你甚至不应该试图自己解析int,除非你知道结果符合 double 。例如。你不能知道这个指针。



例如,考虑以下几点:$ b​​
$ b

  // 6 * 8-bit = 48 bit; 48℃ 53,所以这是OK 
((parseInt(0xffffffffffff,16)+ 2)== parseInt(0xffffffffffff,16))== false
//然而,7 * 8位= 56位; 56 < 53,所以这是不正确
((parseInt(0xffffffffffffff,16)+ 2)== parseInt(0xffffffffffffff,16))== true
//糟糕,比较相等,因为双精度浮点数
//不能实际保存parseInt结果,这仍然远低于64位!

让我们正确处理JS中的64位整数...



如果您只是想进行比较,请使用 UInt64.compare() / Int64.compare()

  //数字==另一个数字
ctypes.UInt64.compare(ctypes.UInt64( 7),ctypes.UInt64(7))== 0
// number!=另一个数字
ctypes.UInt64.compare(ctypes.UInt64(7),ctypes.UInt64 6))!= 0
// number>另一个数字
ctypes.UInt64.compare(ctypes.UInt64(7),ctypes.UInt64(6))> 0
//数字<另一个数字
ctypes.UInt64.compare(ctypes.UInt64(7),ctypes.UInt64(8))< 0

如果您需要结果,但不确定它是否为32位无符号整数,可以检测你是否处理32位无符号整数,这些整数只是打包到 Uint64 中:

  ctypes.UInt64.compare(ctypes.UInt64(7),ctypes.UInt64(0xffffffff))< 0 

以及 Int64 ,但你需要比较最小值和最大值:

  ctypes.Int64.compare(ctypes.Int64(7 ),ctypes.Int64(2147483647))< 0&& 
ctypes.Int64.compare(ctypes.Int64(7),ctypes.Int64( - 2147483648))> 0

因此,一旦您知道或检测到JS ,可以很安全地调用 parseInt
$ b

  var number = ...; 
if(ctypes.UInt64.compare(number,ctypes.UInt64(0xffffffff))> 0){
throw错误(哎呀,我们的代码无法正确处理的意外的大数值) ;
}
chars = parseInt(chars.toString(),10);

(为了完整起见,还有 UInt64.hi() / Int64.hi() UInt64.lo() / Int64.lo()得到真正的64位整数的高低32位,并自己做64位整数数学(问题/ 1652654 /添加-64-bit-numbers-using-32-bit-arithmetic>例如),但要小心头号。 PS: SendMessage 的返回值是 intptr_t 不是 uintptr_t ,因为 SendMessage(hwnd,TB_GETBUTTONTEXT,...)可能在失败时返回 -1 ! / b>

所以把所有这些放在一起(未经测试):

$ p $ var $ SendMessage = user32.declare(
'SendMessageW',
ctypes.winapi_abi,
ctypes.intptr_t,
ctypes.voidptr_t,// HWND
ctypes.uint32_t,// MSG
ctypes.uintptr_t,// WPARAM
ctypes.intptr_t // LPARAM
);
// ...

var chars = SendMessage(hToolbar,TB_GETBUTTONTEXTW,local_tbb.idCommand,ctypes.voidptr_t(0));
if(ctypes.Int64.compare(chars,ctypes.Int64(0))<0){
throw new Error(TB_GETBUTTONTEXT returned a failure(negative value));

if(ctypes.Int64.comare(chars,ctypes.Int64(32768))> 0){
throw new错误(TB_GETBUTTONTEXT返回不合理的大数目> 32KiB );
}
chars = parseInt(chars.toString());


I have this: "ctypes.UInt64("7")"

It is returned by this:

var chars = SendMessage(hToolbar, TB_GETBUTTONTEXTW, local_tbb.idCommand, ctypes.voidptr_t(0));

so

console.log('chars=', chars, chars.toString(), uneval(chars));

gives

'chars=' 'UInt64 {  }' "7" 'ctypes.UInt64("7")'

So I can get the value by going chars.toString(), but I have to run a parseInt on that, is there anyway to read it like a property? Like chars.UInt64?

解决方案

The problem with 64-bit integers in js-ctypes is that Javascript lacks a compatible type. All Javascript numbers are IEEE double precision floating point numbers (double), and those can represent 53-bit integers at most. So you shouldn't even be trying to parse the int yourself, unless you know for a fact that the result would fit into a double. E.g. You cannot know this for pointers.

E.g. consider the following:

// 6 * 8-bit = 48 bit; 48 < 53, so this is OK
((parseInt("0xffffffffffff", 16) + 2) == parseInt("0xffffffffffff", 16)) == false
// However, 7 * 8-bit = 56 bit; 56 < 53, so this is not OK
((parseInt("0xffffffffffffff", 16) + 2) == parseInt("0xffffffffffffff", 16)) == true
// Oops, that compared equal, because a double precision floating point
// cannot actual hold the parseInt result, which is still well below 64-bit!

Lets deal with 64-bit integers in JS properly...

If you just want to comparisons, use UInt64.compare()/Int64.compare(), e.g.

// number == another number
ctypes.UInt64.compare(ctypes.UInt64("7"), ctypes.UInt64("7")) == 0
// number != another number
ctypes.UInt64.compare(ctypes.UInt64("7"), ctypes.UInt64("6")) != 0
// number > another number
ctypes.UInt64.compare(ctypes.UInt64("7"), ctypes.UInt64("6")) > 0
// number < another number
ctypes.UInt64.compare(ctypes.UInt64("7"), ctypes.UInt64("8")) < 0

If you need the result, but are not sure it is a 32-bit unsigned integer, you can detect if you're dealing with 32 bit unsigned integers that are just packed into Uint64:

ctypes.UInt64.compare(ctypes.UInt64("7"), ctypes.UInt64("0xffffffff")) < 0

And the analog for 32-bit signed integers in Int64, but you need to compare minimum and maximum:

ctypes.Int64.compare(ctypes.Int64("7"), ctypes.Int64("2147483647")) < 0 &&
ctypes.Int64.compare(ctypes.Int64("7"), ctypes.Int64("-2147483648")) > 0

So, once you know or detected that something will fit into a JS double, it is safe to call parseInt on it.

var number = ...;
if (ctypes.UInt64.compare(number, ctypes.UInt64("0xffffffff")) > 0) {
  throw Error("Whoops, unexpectedly large value that our code would not handle correctly");
}
chars = parseInt(chars.toString(), 10); 

(For the sake of completeness, there is also UInt64.hi()/Int64.hi() and UInt64.lo()/Int64.lo() to get the high and low 32-bits for real 64-bit integers and do 64-bit integer math yourself (e.g.), but beware of endianess).

PS: The return value of SendMessage is intptr_t not uintptr_t, which is important here because SendMessage(hwnd, TB_GETBUTTONTEXT, ...) may return -1 on failure!

So putting all this together (untested):

var SendMessage = user32.declare(
    'SendMessageW',
    ctypes.winapi_abi,
    ctypes.intptr_t,
    ctypes.voidptr_t, // HWND
    ctypes.uint32_t, // MSG
    ctypes.uintptr_t, // WPARAM
    ctypes.intptr_t // LPARAM
);
// ...

var chars = SendMessage(hToolbar, TB_GETBUTTONTEXTW, local_tbb.idCommand, ctypes.voidptr_t(0));
if (ctypes.Int64.compare(chars, ctypes.Int64("0")) < 0) {
  throw new Error("TB_GETBUTTONTEXT returned a failure (negative value)");
}
if (ctypes.Int64.comare(chars, ctypes.Int64("32768")) > 0) {
  throw new Error("TB_GETBUTTONTEXT returned unreasonably large number > 32KiB");
}
chars = parseInt(chars.toString());

这篇关于如何获得一个UInt64的价值,只有toString的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆