Subject: [ruby-ffi] Re: Using Windows Unicode functions |
From: Quintus |
Date: 1/26/10 10:36 AM |
To: ruby-ffi |
That works! Thank you! So, here's the working code: ------------------------------------ #Encoding: UTF-8 require "ffi" module Test extend FFI::Library ffi_lib "user32" ffi_convention :stdcall attach_function :message_box, :MessageBoxW, [:long, :buffer_in, :buffer_in, :int], :int end string = "Test with umlaut: ä\0".encode("UTF-16LE") #MS expects double NUL at a unicode string's end Test.message_box(0, string, string, 0) ---------------------------------------- Tested with ruby 1.9.1p243 (2009-07-16 revision 24175) [i386- mingw32]. Marvin On 25 Jan., 01:12, Wayne Meissner <wmeiss...@gmail.com> wrote:
<sutn...@gmx.net>:You could try using :buffer_in instead of :string for the parameter types in MessageBoxW. :string in ruby-ffi means 'nul terminated C string', wheras UTF-16 is really more of a binary blob of data. Ruby-ffi checks for nul chars in :string parameters (via StringValueCStr()) to avoid nul-byte poisoning attacks (assuming someone reads a string from an untrusted source), like most other C extensions do. 2010/1/19 QuintusHi there,
;-) ). So far, I've been using the win32-api gem which worked quite well with the Windows Unicode functions (they require UTF-16LE encoded strings, also known as the wchar_t C type I think), but I wasn't able to construct that with ffi.I'm trying to access Windows functions through the ffi gem, but I wasn't that successfull (otherwise I wouldn't post here, I think
Here's my code so far: ------------------------------------- #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 Rubys 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 displayed correct
#The following line causes the error: Test.message_box(0, buffer, buffer, 0) -------------------------------------
*contains* NUL bytes, I know--but I want to use Unicode functions, so: How to do that?This is the error message: ------------------------------------- t2.rb:32:in `message_box': string contains null byte (ArgumentError) from t2.rb:32:in `<main>' ------------------------------------- An UTF-16LE encoded string
My ruby version: ruby 1.9.1p243 (2009-07-16 revision 24175) [i386- mingw32] My OS: Windows Vista Home Premium SP2 (32 bit)
Marvin