This is my stripped down code which isolates my problem:
#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);
}
When I call get_pairs_2 in ruby, I get this error:
TypeError: wrong argument type EV::PairCounter (expected Class)
I've confirmed that C is viewing EV::PairCounter as a superclass, and not as a string or something.
By the way, this is what the C extension API says about Data_Wrap_Struct:
Encapsulate C data into Ruby object
To wrap and objectify a C pointer as a Ruby object (so called DATA), use Data_Wrap_Struct().
Data_Wrap_Struct(klass, mark, free, ptr)
Data_Wrap_Struct() returns a created DATA object. The klass argument is the class for the DATA object. The mark argument is the function to mark Ruby objects pointed by this data. The free argument is the function to free the pointe开发者_高级运维r allocation. If this is -1, the pointer will be just freed. The functions mark and free will be called from garbage collector.
The issue was that klass in Data_Wrap_Struct(klass, mark, free, ptr) is the klass you are returning, not the klass you are sending the data to. So klass is a ruby class defined and populated in C, and then returned to ruby with this function.
精彩评论