我正在使用Ruby 1.8上的Ruby-FFI来包装一个使用UTF-16LE字符串的库。该库有一个返回这样一个String的C函数。
我是否用
包装函数attach_function [:getVersion, [], :pointer]
并在返回的指针上调用read_string
,或者是否用
attach_function [:getVersion, [], :string]
我得到的只是第一个字符,因为第二个字符为空(\000
),因此,FFI停止在那里读取字符串,显然是因为它假设它正在处理正常的单个字符-null终止字符串。
我需要做些什么,可能是在初始化我的Ruby程序或FFI或其他方面,让它知道我希望字符串是UTF-16LE编码的吗?我怎么能绕过这个?
答案 0 :(得分:1)
好的,这是我到目前为止(不优雅)的解决方法。它涉及到FFI :: Pointer添加一个方法。在我的库的上下文中调用应该是安全的,因为所有字符串都应该是UTF-16LE编码的,否则,它可能不是很好,因为它可能永远不会遇到double null并且只会继续读取内存中字符串的边界。
module FFI
class Pointer
# Read string until we encounter a double-null terminator
def read_string_dn
cont_nullcount = 0
offset = 0
# Determine the offset in memory of the expected double-null
until cont_nullcount == 2
byte = get_bytes(offset,1)
cont_nullcount += 1 if byte == "\000"
cont_nullcount = 0 if byte != "\000"
offset += 1
end
# Return string with calculated length (offset) including terminator
get_bytes(0,offset+1)
end
end
end
答案 1 :(得分:0)
基于相同想法的更优雅的解决方案。也处理编码。
module FFI
class Pointer
def read_wstring
offset = 0
while get_bytes(offset, 2) != "\x00\x00"
offset += 2
end
get_bytes(0, offset).force_encoding('utf-16le').encode('utf-8')
end
end
end