4

我正在尝试使用小提琴在 Ruby 中定义Tinn C 库,但它给了我一个结构错误

廷恩.h

typedef struct
{
    // All the weights.
    float* w;
    // Hidden to output layer weights.
    float* x;
    // Biases.
    float* b;
    // Hidden layer.
    float* h;
    // Output layer.
    float* o;
    // Number of biases - always two - Tinn only supports a single hidden layer.
    int nb;
    // Number of weights.
    int nw;
    // Number of inputs.
    int nips;
    // Number of hidden neurons.
    int nhid;
    // Number of outputs.
    int nops;
}
Tinn;

float* xtpredict(Tinn, const float* in);

float xttrain(Tinn, const float* in, const float* tg, float rate);

Tinn xtbuild(int nips, int nhid, int nops);

红宝石小提琴

module Tinn
    extend Fiddle::Importer
    dlload './tinn.so'

    Tinn = struct [
        # All the weights.
        'float* w',
        # Hidden to output layer weights.
        'float* x',
        # Biases.
        'float* b',
        # Hidden layer.
        'float* h',
        # Output layer.
        'float* o',
        # Number of biases - always two - Tinn only supports a single hidden layer.
        'int nb',
        # Number of weights.
        'int nw',
        # Number of inputs.
        'int nips',
        # Number of hidden neurons.
        'int nhid',
        # Number of outputs.
        'int nops'
    ]

    extern 'float* xtpredict(Tinn, const float* in)'

    extern 'float xttrain(Tinn, const float* in, const float* tg, float rate)'

    extern 'Tinn xtbuild(int nips, int nhid, int nops)'
end

我收到这样的错误

/home/arjun/.rbenv/versions/2.3.3/lib/ruby/2.3.0/fiddle/cparser.rb:177:in `parse_ctype': unknown type: Tinn (Fiddle::DLError)
    from /home/arjun/.rbenv/versions/2.3.3/lib/ruby/2.3.0/fiddle/cparser.rb:90:in `block in parse_signature'
    from /home/arjun/.rbenv/versions/2.3.3/lib/ruby/2.3.0/fiddle/cparser.rb:90:in `collect'
    from /home/arjun/.rbenv/versions/2.3.3/lib/ruby/2.3.0/fiddle/cparser.rb:90:in `parse_signature'
    from /home/arjun/.rbenv/versions/2.3.3/lib/ruby/2.3.0/fiddle/import.rb:163:in `extern'
    from rb_tinn.rb:31:in `<module:Tinn>'
    from rb_tinn.rb:4:in `<main>'

第 31 行指向我们将 struct 作为参数传递的第一个函数 float* xtpredict(Tinn, const float* in)

我已经将 Tinn 定义为一个结构,但它仍然给出错误。

4

1 回答 1

4

Ruby 中带有 Fiddle 的结构有点误导,因为它是其 C 对应物的直接模拟。许多使结构变得简单和用户友好的特性在它的 Ruby 表示中是缺乏的。

要记住的主要原则是 aFiddle::CStruct实际上只不过是 gloryified Fiddle::Pointer,实际上是它的子类。主要限制是您只能在其中声明原始类型。不像在 C 语言中,如果你定义一个结构,那么你可以将它用作另一个结构中的类型、返回值等。

这仍然可以在 Ruby 中完成,尽管文档对这个问题很清楚。正如我之前所说,请记住 Ruby 结构派生自Fiddle::Pointer,您只需void*在签名声明中使用(或Fiddle::TYPE_VOIDP取决于您是否使用 CParser)。

在你上面的例子中,一旦你声明了你的结构,你就可以像这样定义你的方法签名:

float* xtpredict(void* tinn, const float* in)

将您的结构类型替换void*为类型的名称,然后您可以将结构直接传递给它并获得您期望的所需行为。

获取从方法返回的结构的方法相同。再次void*在签名中使用 Ruby 将返回一个Fiddle::Pointer对象。该指针包含结构在内存中的地址。由于结构在其初始化方法中采用地址,因此使用返回的指针来初始化您的结构,它将在内存中的该位置创建。

ptr = getMyStruct
MyStruct.new(ptr.to_i)

相反,如果我没记错的话,我相信你也可以这样使用它:

ptr = getMyStruct
MyStruct.new(ptr.ptr)
于 2018-06-24T04:34:43.300 回答