我正在使用TCL 8.4.20。
所以我有以下代码:
set a [binary format H2 1]
set b [binary format H2 2]
set c [binary format H2 3]
set bytes $a
append bytes $a
append bytes $b
append bytes $c
puts $bytes
我在TCL的C源代码中的Tcl_PutsObjCmd()函数中设置了一个断点,我看到它的参数$ bytes是string类型,而我希望它是bytearray。
问题1 :为什么?从第一个赋值到最后一个赋值,“bytes”只接受二进制数据。
我做这个实验的原因是,我们在C中有一个TCL扩展命令,它期望命令参数是字节数组类型 - 它检查值的typePtr应该是tclByteArrayType。我的TCL代码目前在此命令上失败,因为传递给命令的数据是字符串类型,就像上面的演示一样。
我用google搜索,似乎制作字节数组对象的“正确”方法是首先准备好每个字节,最后使用一个“二进制格式”命令将所有字节放入一个。但这对我目前的TCL代码来说是一个相当大的变化。
问题2 :鉴于我已经有了一个TCL变量,其数据都是二进制文件(使用“二进制格式”为每个字节创建并使用“append”组合在一起),而其类型为字符串,如何通过一些TCL操作将其内部类型更改为“bytearray”?
答案 0 :(得分:0)
从技术上讲,内部类型不是保证属性。一切都是一个字符串。无论什么时候感觉,代码都可以闪烁一下。依赖于内部类型的代码通常非常脆弱或彻底破坏。
所以你的C代码应该调用Tcl_GetByteArrayFromObj()
而不是窥视参数内部。如果对象还没有byteArray表示,则执行正确的转换。
关于您的问题:
为什么两个字节数组的append
不保持字节数组类型?
至少8.6,如果你做得对,从不触发创建字符串代表。
在tkcon中运行它,append
将值转换为字符串:
() 98 % set a [binary format H2 1]
() 99 % set b [binary format H2 1]
() 100 % ::tcl::unsupported::representation $a
value is a bytearray with a refcount of 2, object pointer at 0000000005665420, internal representation 000000000587B280:0000000005665240, string representation ""
() 101 % ::tcl::unsupported::representation $b
value is a bytearray with a refcount of 2, object pointer at 000000000564EEB0, internal representation 000000000587B4A0:00000000056590E0, string representation ""
() 102 % set x $a
() 103 % ::tcl::unsupported::representation $x
value is a bytearray with a refcount of 4, object pointer at 0000000005665420, internal representation 000000000587B280:0000000005665240, string representation ""
() 104 % append x $b
() 105 % ::tcl::unsupported::representation $x
value is a string with a refcount of 3, object pointer at 0000000005663F50, internal representation 0000000005896BA0:000000000564F030, string representation ""
这种情况发生了,因为bytearray有一个字符串rep(由于Tkcon回显该值)而创建。 append
优化仅适用于'纯'字节数组,例如没有字符串代表的bytearrays。这类似于“纯”列表的一些优化。
所以它就像这样,防止闪烁的结果回声:
() 106 % set b [binary format H2 1]; puts "pure"
pure
() 107 % set a [binary format H2 1]; puts "pure"
pure
() 108 % set x $a; puts "pure"
pure
() 109 % ::tcl::unsupported::representation $a
value is a bytearray with a refcount of 3, object pointer at 0000000005658780, internal representation 000000000587B320:0000000005658CF0, no string representation
() 110 % ::tcl::unsupported::representation $b
value is a bytearray with a refcount of 2, object pointer at 000000000564ED60, internal representation 000000000587B500:0000000005658750, no string representation
() 111 % ::tcl::unsupported::representation $x
value is a bytearray with a refcount of 3, object pointer at 0000000005658780, internal representation 000000000587B320:0000000005658CF0, no string representation
() 112 % append x $b; puts "pure"
pure
() 113 % ::tcl::unsupported::representation $x
value is a bytearray with a refcount of 2, object pointer at 0000000005658690, internal representation 00000000058A5C60:0000000005658960, no string representation
请注意无字符串表示部分。
如何将字符串转换为bytearray
只做二进制格式:
set x [binary format a* $x]