0

我正在使用 Ruby 1.8 上的 Ruby-FFI 来包装一个使用 UTF-16LE 字符串的库。该库有一个返回此类字符串的 C 函数。

我是否用

attach_function [:getVersion, [], :pointer]

并调用read_string返回的指针,或者我是否用

attach_function [:getVersion, [], :string]

我得到的只是第一个字符,因为第二个字符是 null ( \000),因此,FFI 停止在那里读取字符串,显然是因为它假设它正在处理一个正常的、单空终止的字符串。

我需要做些什么,也许是在我的 Ruby 程序或 FFI 或其他方式的初始化中,让它知道我希望字符串是 UTF-16LE 编码的?我还能如何解决这个问题?

4

2 回答 2

1

好的,这是我到目前为止的(不优雅的)解决方法。它涉及向 FFI::Pointer 添加一个方法。在我的库的上下文中调用应该是安全的,因为所有字符串都应该是 UTF-16LE 编码的,但否则,它可能不好,因为它可能永远不会遇到双空,并且只会继续阅读过去内存中字符串的边界。

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
于 2012-02-15T13:32:05.540 回答
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
于 2018-05-29T17:19:36.840 回答