Ruby小提琴定义结构

时间:2018-06-10 15:18:34

标签: c ruby fiddle

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

Tinn.h

import numpy as np

np.matmul(matrix_2, vector_2)

Out[ ]: 
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-10-752f945775e1> in <module>()
----> 1 np.matmul(matrix_2, vector_2)

ValueError: shapes (3,2) and (3,) not aligned: 2 (dim 1) != 3 (dim 0)

Ruby小提琴

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

第31行指向我们传递struct作为参数的第一个函数 /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>'

我已经将Tinn定义为结构,但它仍然是错误。

1 个答案:

答案 0 :(得分:3)

在Ruby中使用Fiddle的结构作为其C对应物的直接类似物,会产生误导。在Ruby表示中缺少使结构简单和用户友好的许多功能。

要记住的主要原则是Fiddle::CStruct实际上只是美化的Fiddle::Pointer,实际上是它的子类。主要限制是您只能在其中声明基本类型。与C语言中定义结构不同,您可以将其用作其他结构中的类型,返回值等。

尽管有关该问题的文档还很少,但这仍然可以在Ruby中完成。如前所述,请记住,Ruby结构是从Fiddle::Pointer派生的,您只需在签名声明中使用void*(或Fiddle::TYPE_VOIDP取决于您是否在使用CParser) 。

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

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

void*代替结构类型,而不是类型名称,然后可以将结构直接传递给它,并获得所需的预期行为。

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

ptr = getMyStruct
MyStruct.new(ptr.to_i)

相反,如果记忆正确,我相信您也可以像这样使用它:

ptr = getMyStruct
MyStruct.new(ptr.ptr)