如何获取 UInt64 的值,只有 toString 的方法?

Noi*_*art 1 javascript firefox-addon jsctypes

我有这个: "ctypes.UInt64("7")"

它是由这个返回的:

var chars = SendMessage(hToolbar, TB_GETBUTTONTEXTW, local_tbb.idCommand, ctypes.voidptr_t(0));
Run Code Online (Sandbox Code Playgroud)

所以

console.log('chars=', chars, chars.toString(), uneval(chars));
Run Code Online (Sandbox Code Playgroud)

'chars=' 'UInt64 {  }' "7" 'ctypes.UInt64("7")'
Run Code Online (Sandbox Code Playgroud)

所以我可以通过 go 来获取值chars.toString(),但我必须在上面运行一个parseInt,反正有没有像属性一样读取它?喜欢chars.UInt64

nma*_*ier 5

js-ctypes 中 64 位整数的问题在于 Javascript 缺乏兼容类型。所有 Javascript 数字都是 IEEE 双精度浮点数 ( double),它们最多可以表示53 位整数。因此,您甚至不应该尝试自己解析 int,除非您知道结果适合double. 例如,您无法通过指针知道这一点。

例如,考虑以下事项:

// 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!
Run Code Online (Sandbox Code Playgroud)

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

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

// 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
Run Code Online (Sandbox Code Playgroud)

如果您需要结果,但不确定它是一个 32 位无符号整数,您可以检测您是否正在处理刚刚打包到的 32 位无符号整数Uint64

ctypes.UInt64.compare(ctypes.UInt64("7"), ctypes.UInt64("0xffffffff")) < 0
Run Code Online (Sandbox Code Playgroud)

以及 中 32 位有符号整数的模拟Int64,但您需要比较最小值和最大值:

ctypes.Int64.compare(ctypes.Int64("7"), ctypes.Int64("2147483647")) < 0 &&
ctypes.Int64.compare(ctypes.Int64("7"), ctypes.Int64("-2147483648")) > 0
Run Code Online (Sandbox Code Playgroud)

因此,一旦您知道或检测到某些内容适合 JS double,就可以安全地调用parseInt它。

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); 
Run Code Online (Sandbox Code Playgroud)

(为了完整起见,还有UInt64.hi()/Int64.hi()UInt64.lo()/Int64.lo()来获取真实 64 位整数的高和低 32 位并自己进行 64 位整数数学运算(例如),但要注意字节序)。

PS:的返回值SendMessageintptr_t不是uintptr_t,这是很重要的,因为在这里SendMessage(hwnd, TB_GETBUTTONTEXT, ...)可能会返回-1失败!

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

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());
Run Code Online (Sandbox Code Playgroud)