Ruby Noobie:如何在 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>
有一个很好的建议来尝试内存指针类型,我今天下班后会尝试一下。
I'm having some beginner problems setting an FFI struct in Ruby. What I want to do is pass a pointer to a C string by setting a string property in an FFI::Struct object:
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!
But when I run the code I get this error:
jukebox.rb:44:in `[]=': Cannot set :string fields (ArgumentError)
from jukebox.rb:44:in `<main>'
So I don't really know where to go from here.
Also, if you know of any good documtation or tutorials on this subject please leave a response! So far I have found the wiki documentation on Project Kenai
very useful but the more the merrier!
Thanks!
I have tried to declare the string data members as [:char, 5] but that gives another error:
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>
There is a good suggestion to try out the memory pointer type and I will try that after work today.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
因此,感谢 Pesto(已接受)的回答,我找到了解决方案。 如果缓冲区中有零字节,则 write_string 提前返回(遵循 C 字符串语义)。 这是为将来可能遇到此问题的任何人提供的代码。
So thanks to the answer from Pesto (accepted) I have found a solution. write_string returns early if there is a zero byte in the buffer (follows c-string semantics). Here is the code for anyone who might stumble onto this problem in the future.
FFI 自动拒绝设置字符串。 尝试将其从 :string 更改为 :char_array,如此页面中所述:
如果这不起作用,您将不得不使用 :pointer 并将其转换回字符串。 它没有很好的记录,但 MemoryPointer 有一个 一堆可用函数,例如
write_string
,应该会有所帮助。FFI automatically rejects setting strings. Try changing it from :string to :char_array, as mentioned on this page:
If that doesn't work, you're going to have to use a :pointer and convert it back into a string. It's not well documented, but MemoryPointer has a bunch of available functions, such as
write_string
, that should help.