Ruby Noobie: Как установить строковое значение в структуре FFI - PullRequest
2 голосов
/ 13 апреля 2009

У меня проблемы с новичком при настройке структуры FFI в Ruby. То, что я хочу сделать, это передать указатель на строку C, установив свойство строки в объекте FFI :: Struct:

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 очень полезно, но чем больше, тем лучше!

Спасибо!

Я пытался объявить строковые данные как [: 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 ]

1 голос
/ 14 апреля 2009

Так что благодаря ответу Песто (принято) я нашел решение. write_string возвращает рано, если в буфере есть нулевой байт (следует семантике c-строки) Вот код для тех, кто может столкнуться с этой проблемой в будущем.

# 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)
0 голосов
/ 14 апреля 2009

FFI автоматически отклоняет установочные строки. Попробуйте изменить его с: string на: char_array, как указано на этой странице :

: char_array - используется ТОЛЬКО в макете структуры, где struct имеет строку в стиле C (char []) в качестве члена

Если это не сработает, вам придется использовать указатель: и преобразовать его обратно в строку. Это плохо документировано, но MemoryPointer имеет набор доступных функций , таких как write_string, которые должны помочь.

...