Ruby Noobie:如何在FFI Struct中设置字符串值

时间:2009-04-13 19:46:17

标签: ruby ffi

我在Ruby中设置FFI结构时遇到了一些初学者问题。我想要做的是通过在FFI :: Struct对象中设置字符串属性来传递指向C字符串的指针:

class SpSessionConfig < FFI::Struct
  layout :api_version,          :int,
           :cache_location,       :string,
           :settings_location,    :string,
           :application_key,      :pointer,
           :application_key_size, :int,
           :user_agent,           :string,
           :sp_session_callbacks, :pointer,
           :user_data,            :pointer 
  end
end


sessionConf = SpotifyLibrary::SpSessionConfig.new() 
puts sessionConf # => '#<SpotifyLibrary::SpSessionConfig:0x9acc00c>'

sessionConf[:api_version] = 1
puts "Api Version: #{sessionConf[:api_version]}"

myTempDir = "tmp"
sessionConf[:cache_location] = myTempDir # !Error!

但是当我运行代码时,我收到了这个错误:

jukebox.rb:44:in `[]=': Cannot set :string fields (ArgumentError)
from jukebox.rb:44:in `<main>'

所以我真的不知道从哪里开始。

另外,如果您知道有关此主题的任何好的文档或教程,请留下回复!到目前为止,我已在Project Kenai找到了wiki文档  非常有用,但越多越好!

谢谢!

我试图将字符串数据成员声明为[:char,5],但这会产生另一个错误:

jukebox.rb:44:in `put': put not supported for FFI::StructLayoutBuilder::ArrayField_Signed8_3 (ArgumentError)
    from jukebox.rb:44:in `[]='
    from jukebox.rb:44:in `<main>

有一个很好的建议尝试记忆指针类型,我会在今天下班后尝试。

2 个答案:

答案 0 :(得分:1)

所以感谢Pesto的回答(接受),我找到了解决方案。如果缓冲区中存在零字节,则write_string会提前返回(遵循c-string语义)。以下是可能在将来偶然发现此问题的任何人的代码。

# Open my application key file and store it in a byte array
appkeyfile = File.read("spotify_appkey.key")

# get the number of bytes in the key
bytecount = appkeyfile.unpack("C*").size

# create a pointer to memory and write the file to it
appkeypointer = FFI::MemoryPointer.new(:char, bytecount)
appkeypointer.put_bytes(0, appkeyfile, 0, bytecount)

答案 1 :(得分:0)

FFI会自动拒绝设置字符串。尝试将其更改为:string to:char_array,如this page中所述:

  

:char_array - 仅在结构布局中使用,其中struct具有C样式字符串(char [])作为成员

如果这不起作用,您将不得不使用:指针并将其转换回字符串。它没有详细记录,但MemoryPointer有一个bunch of available functions,例如write_string,应该有所帮助。