Ruby Fiddle определить структуру - PullRequest
0 голосов
/ 10 июня 2018

Я пытаюсь определить Tinn C lib в Ruby, используя fiddle, но он выдает ошибку с struct

Tinn.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);

Ruby Fiddle

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)

Я уже определил Тинн как структуру, но все равно он выдает ошибку.

1 Ответ

0 голосов
/ 24 июня 2018

Структуры с Fiddle в Ruby немного вводят в заблуждение, поскольку являются прямым аналогом своего аналога 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.Этот указатель содержит адрес, по которому структура находится в памяти.Поскольку структуры принимают адрес в своем методе инициализации, используйте возвращенный указатель для инициализации вашей структуры, и он будет создан в этом месте в памяти.

ptr = getMyStruct
MyStruct.new(ptr.to_i)

И наоборот, если память мне не изменяет, я вам верюможно также использовать это так:

ptr = getMyStruct
MyStruct.new(ptr.ptr)
...