Что я должен вернуть как класс в Data_Wrap_Struct?

Это мой урезанный код, который изолирует мою проблему:

#include "ruby.h"
#include "stdlib.h"

typedef struct HandValues {
    double pair1;
    double pair2;
} HandValues;

static VALUE 
get_pairs_2(self) 
  VALUE self;
{

    HandValues *MadeHand = (HandValues *) malloc(sizeof(HandValues));
    MadeHand->pair1 = 5;

    return Data_Wrap_Struct(self, NULL, NULL, &MadeHand);
}

void Init_ev() {
    rb_eval_string("require './lib/ev/pair_counter'");
    VALUE PairCounter = rb_path2class("EV::PairCounter");
    rb_define_method(PairCounter, "get_pairs_2", get_pairs_2, 0);
}

Когда я вызываю get_pairs_2 в ruby, я получаю эту ошибку:

TypeError: wrong argument type EV::PairCounter (expected Class)

Я подтвердил, что C рассматривает EV::PairCounter как суперкласс, а не как строку или что-то в этом роде.

Кстати, вот что говорит API расширения C о Data_Wrap_Struct:

Инкапсулировать данные C в объект Ruby

Чтобы обернуть и объективировать указатель C как объект Ruby (так называемый DATA), используйте Data_Wrap_Struct().

Data_Wrap_Struct(klass, mark, free, ptr)

Data_Wrap_Struct() возвращает созданный объект DATA. Аргумент klass — это класс объекта DATA. Аргумент mark — это функция, которая помечает объекты Ruby, на которые указывают эти данные. Аргумент free — это функция для освобождения выделения указателя. Если это -1, указатель будет просто освобожден. Функции mark и free будут вызываться из сборщика мусора.


person Jeremy Smith    schedule 23.06.2011    source источник
comment
Если у вас есть собственный stdlib.h, вы действительно должны назвать его по-другому; если вы полагаетесь на реализации stdlib.h, правильная строка будет #include <stdlib.h> :)   -  person pmg    schedule 23.06.2011
comment
Какова цель помещения VALUE self; между сигнатурой функции и телом?   -  person JAB    schedule 23.06.2011
comment
@JAB: это объявление в старом стиле. Недавно (после 1989 г.) вместо этого мы начали использовать прототипы; но компиляторы в основном обратно совместимы и (если вы не попросите их пожаловаться) спокойно принимают старый синтаксис.   -  person pmg    schedule 23.06.2011
comment
@pmg: Ты забыл сказать ему, чтобы он убирался с твоей лужайки.   -  person mu is too short    schedule 23.06.2011


Ответы (1)


Проблема заключалась в том, что класс в Data_Wrap_Struct(klass, mark, free, ptr) — это класс, который вы возвращаете, а не класс, которому вы отправляете данные. Таким образом, klass — это класс ruby, определенный и заполненный в C, а затем возвращенный в ruby ​​с помощью этой функции.

person Jeremy Smith    schedule 23.06.2011
comment
например ' статическое ЗНАЧЕНИЕ createMat4 (ЗНАЧЕНИЕ obj) { void *p=malloc(sizeof(double)*16); printf(создать %p\n,p); ЗНАЧЕНИЕ v; v=Data_Wrap_Struct(v, NULL, NULL, p); вернуть v; }' - person Chris Camacho; 21.07.2012