Pergunta

Eu estou tendo alguns problemas iniciantes Definição de um struct FFI em Ruby. O que eu quero fazer é passar um ponteiro para uma string C, definindo uma propriedade string em uma FFI :: Struct objeto:

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!

Mas quando eu executar o código eu recebo este erro:

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

Então, eu realmente não sei para onde ir a partir daqui.

Além disso, se você souber de qualquer bom documtation ou tutoriais sobre este assunto, por favor deixar uma resposta! Até agora eu encontrei a documentação wiki em projeto Kenai muito útil, mas quanto mais, melhor!

Obrigado!

Eu tentei declarar os membros de dados String como [: char, 5], mas que lhe dá outro erro:

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>

Não é uma boa sugestão para experimentar o tipo de ponteiro de memória e vou tentar que depois do trabalho hoje.

Foi útil?

Solução

FFI rejeita automaticamente seqüências de configuração. Tente mudá-lo a partir de: corda para: char_array, como mencionado na desta página :

: char_array - utilizado apenas em um layout struct onde struct tem uma série de estilo C (char []) como membro

Se isso não funcionar, você vai ter que usar um: ponteiro e convertê-lo de volta em uma string. Não é bem documentado, mas MemoryPointer tem um monte de funções disponíveis , como write_string, que deve ajudar.

Outras dicas

Assim, graças à resposta de Pesto (aceite) Eu encontrei uma solução. write_string retornos cedo se existe um zero bytes no tampão (segue semântica string C). Aqui está o código para quem pode tropeçar este problema no futuro.

# 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)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top