2009-04-13 9 views
2

RubyでFFI構造体を設定する際の初心者の問題があります。Ruby Noobie:FFI構造体の文字列値を設定する方法

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>' 
を私は何をしたいFFIに:: Structオブジェクトを文字列プロパティを設定することにより、C列へのポインタを渡しています

ここからどこに行くのか本当に分かりません。

また、このテーマに関する適切な文書やチュートリアルについて知っていれば、回答を残してください!これまでのところ、wikiのドキュメントはProject Kenai で非常に便利ですが、もっと愉快です!

ありがとうございます!

私のように文字列データメンバを宣言しようとしている[: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> 

ありメモリポインタ型を試してみるには良い提案があり、私はそれをしようとします今日の仕事の後。

+1

私はあなたのタイトルが好きです。偉大な韻! – jjnguy

答えて

0

FFIは設定文字列を自動的に拒否します。 this pageに述べたように、char_array:に文字列:からそれを変更してみてください

:char_array - used ONLY in a struct layout where struct has a C-style string (char []) as a member

問題が解決しない場合は、あなたが使用する必要があるとしている:ポインタをして戻って文字列に変換します。それは十分に文書化されていませんが、MemoryPointerはbunch of available functions(例えば、write_string)のように役立ちます。

+0

情報をありがとう、本当に正しい方向に私を設定します。私は:char配列を試してみましたが、struct宣言でうまくいきません。編集した質問をご覧ください。 – mikelong

+0

私はあなたの提案がお金の上にメモリのポインタを使用すると思う、私はそれを試してみましょう今日は仕事と更新後ここで。ご協力いただきありがとうございます。 – mikelong

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) 
関連する問題