新手问题 Ruby C extension 中怎么把 C wchar 类型和 ruby string 互相转换?

gihnius · 2015年05月04日 · 最后由 luikore 回复于 2015年05月04日 · 2626 次阅读

没有找到相关的 API,只有默认的 string <-> char*。

是否可以把 wchar 转成 char 在通过相关的 api 互转

请问你这个 wchar 是哪个 wchar? 可否提供更详细的信息?

  • 如果你指的是 Win32 API 的 WCHAR, 它是 UTF-16 内码,little endian (UTF-16LE).
  • 如果你指的是 wchar_t, 不同平台的 wchar_t 是不同长度的,有的是是 UTF-16 有的是 UTF-32, 还有别的,而且有 big endian/little endian 的区别 (x86 一般都是 little endian, 不过最好自己做下试验先).

弄清楚内码以后,强转成 char* 交给 rb_enc_str_new, 然后再调用 rb_str_encode 或者在 ruby 方面用 String#encode 方法转换回 utf-8 的字符串。

以 Win32 API WCHAR 为例,它是 UTF-16LE 内码,所以对应的字节数目是字符串长度乘以 2, 假设你有 wchar_ptr, wchar_len

#include <ruby/encoding.h>

.....

volatile VALUE s;
s = rb_enc_str_new((char*)wchar_ptr, wchar_len * 2, rb_enc_find("UTF-16LE"));
s = rb_str_encode(s, rb_enc_from_encoding(rb_utf8_encoding()), 0, Qnil);

假设你有个 Ruby 字符串 s

s = rb_str_encode(s, rb_enc_from_encoding(rb_enc_find("UTF-16LE")), 0, Qnil);
WCHAR* wchar_ptr = (WCHAR*)RSTRING_PTR(s);
int wchar_len = RSTRING_LEN(s) / 2;

基础知识见: http://www.rubydoc.info/stdlib/core/file/README.EXT

找 API 只能看头文件咯: http://rxr.whitequark.org/mri/ident?i=rb_str_encode

另外,如果你在 C++, 那个强制转换会稍微麻烦点,得用 reinterpret_cast<>

#2 楼 @luikore 谢谢。 我是指 wchar.h 里面定义的 wchar_t。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号