Ffi: How to use wchar_t strings?

Hello,

I’m trying to use the ffi gem to work with some WinAPI functions. Till
now, I’ve used the win32-api gem which worked quite well, but I’d like
to try out something new (and maybe easier :wink: ). So, here’s my
question: How do I send a Unicode string (encoded in UTF-16LE) to a
WinAPI function?

This my code:

#Encoding: UTF-8
require “ffi”

module Test
extend FFI::Library

ffi_lib “user32”
ffi_convention :stdcall

attach_function :message_box, :MessageBoxW, [:long, :string, :string,
:int], :int
end

module Test2
extend FFI::Library

CP_UTF8 = 65001
MB_PRECOMPOSED = 0x00000001

ffi_lib “kernel32”
ffi_convention :stdcall

attach_function :get_last_error, :GetLastError, [], :long
attach_function :multi_byte_to_wide_char, :MultiByteToWideChar,
[:uint, :int, :string, :int, :buffer_out, :int], :int
end

buffer = “\0” * 100_000

#I know, I could use Rubies built-in encoding functions
#and I WILL do so, but for now this is to ensure
#everything is 100% correct as MS it expects.
ret = Test2.multi_byte_to_wide_char(Test2::CP_UTF8, 0, “Test”,
“Test”.length, buffer, buffer.length)

buffer.force_encoding(“UTF-16LE”)
puts buffer.encode(“ISO-8859-1”).rstrip #Everything correct

#The following line causes the error:
Test.message_box(0, buffer, buffer, 0)

This is the error message:

t2.rb:32:in message_box': string contains null byte (ArgumentError) from t2.rb:32:in

An UTF-16LE encoded string contains NUL bytes, I know–but I want to
use Unicode functions, so: How to do that?

My ruby version: ruby 1.9.1p243 (2009-07-16 revision 24175)
[i386-mingw32]
My OS: Windows Vista Home Premium SP2 (32 bit)

Marvin

This is the error message:

t2.rb:32:in message_box': string contains null byte (ArgumentError) from t2.rb:32:in

Might be a bug in ffi. I’d ping their group.
-r

On Jan 18, 2:06 pm, Marvin Gülker [email protected] wrote:

#Encoding: UTF-8
end
attach_function :get_last_error, :GetLastError, [], :long
“Test”.length, buffer, buffer.length)
t2.rb:32:in message_box': string contains null byte (ArgumentError) from t2.rb:32:in

An UTF-16LE encoded string contains NUL bytes, I know–but I want to
use Unicode functions, so: How to do that?

I think because :string definition is expecting a Ruby string, not a
memory buffer as you’re trying to send.

wchar_t should be defined as a new type and a proper memory pointer
and buffer should be used to marshal the string from Ruby to the C
realm :slight_smile:

I suggest also bring this topic to FFI group:

http://groups.google.com/group/ruby-ffi

Where you could get better pointers than my vague description.

Cheers,

Luis L. wrote:

I think because :string definition is expecting a Ruby string, not a
memory buffer as you’re trying to send.

wchar_t should be defined as a new type and a proper memory pointer
and buffer should be used to marshal the string from Ruby to the C
realm :slight_smile:
Maybe true. I’m new to ffi, so I’ll have to look how to define my own
type.

I suggest also bring this topic to FFI group:

http://groups.google.com/group/ruby-ffi

Where you could get better pointers than my vague description.
I’ve done so:
http://groups.google.com/group/ruby-ffi/browse_thread/thread/ada0ea99600b7fa1

Marvin