【问题标题】:How to wrap function in Ruby FFI method that takes struct as argument?如何在以结构为参数的 Ruby FFI 方法中包装函数?
【发布时间】:2012-02-17 10:30:12
【问题描述】:

我正在尝试使用 ruby​​-ffi 从共享对象调用函数。我将以下内容编译成一个共享对象:

#include <stdio.h>

typedef struct _WHAT {
  int d;
  void * something;
} WHAT;

int doit(WHAT w) {
  printf("%d\n", w.d);
  return w.d;
}

问题是,如何在Ruby 中用attach_function 声明函数? Ruby 的参数列表中的结构参数(WHAT w)是如何定义的?它不是 :pointer,而且似乎不适合 ruby​​-ffi 文档中描述的任何其他可用类型,那么它会是什么?

【问题讨论】:

    标签: ruby ffi


    【解决方案1】:

    https://github.com/ffi/ffi/wiki/Structs 中检查如何使用结构,适合您的情况:

    class What < FFI::Struct
      layout :d, :int,
             :something, :pointer
    end
    

    现在附加函数,参数,因为你是按值传递结构,将是What.by_value(用你命名的任何东西替换What上面的结构类):

    attach_function 'doit', [What.by_value],:int
    

    现在如何调用函数

    mywhat = DoitLib::What.new
    mywhat[:d] = 1234
    DoitLib.doit(mywhat)
    

    现在是完整的文件:

    require 'ffi'
    
    module DoitLib
      extend FFI::Library
      ffi_lib "path/to/yourlibrary.so"
    
      class What < FFI::Struct
        layout :d, :int,
               :something, :pointer
      end
    
      attach_function 'doit', [What.by_value],:int
    
    end
    
    mywhat = DoitLib::What.new
    mywhat[:d] = 1234
    DoitLib.doit(mywhat)
    

    【讨论】:

    • 谢谢豪尔赫。我的印象是,如果参数没有在 C 库中定义为指针,则需要进行一些其他特殊处理。
    • 抱歉,Jorge,但是当我运行此代码时,它会返回一个看起来更像地址的长数字,而不是我传入的整数。你确定吗?
    • 我错过了将调用约定放在示例中,您可以尝试将 ffi_convention :stdcall 放在 ffi_lib ... 之后。如果不尝试ffi_convention :default(尽管我认为这是默认设置,您不需要指定它)。让我知道这是否有任何改变。
    • 别在意前面的评论,我清理了一个快速库和一个测试,并得到了与您描述的相同的行为(大数字而不是预期的 int)。如果我发现发生了什么事,让我回复你。
    • 谢谢豪尔赫,我都试过了,但我仍然得到相同的结果。我还尝试将参数列表中的 :pointer 替换为 FFI::Struct 类的名称(如您的示例中的 What),如以下 SO 问题所示,但没有任何效果:stackoverflow.com/questions/5372483/…
    猜你喜欢
    • 1970-01-01
    • 2019-02-05
    • 1970-01-01
    • 2018-10-10
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2021-01-08
    相关资源
    最近更新 更多