librelist archives

« back to archive

from_ruby on complex types (and to_ruby)

from_ruby on complex types (and to_ruby)

From:
John O. Woods
Date:
2010-05-27 @ 19:07
I'm not quite clear how to implement from_ruby for different complex types
in C++.

For example, right now, I have this object that should be really easy to
turn into an :options => {:symbol => true, :other_symbol => false} type of
hash (as used in Rails).

using std::string;
class cparams {
public:
    cparams(const string& name) : classifier(name), k(0) { }

    string classifier;
    uint k;

#ifdef RICE
    Rice::Object to_h() const {
        Rice::Hash h;
        h[ Rice::Symbol("classifier")   ]   = to_ruby<string>(classifier);
        if (k > 0) h[ Rice::Symbol("k") ]   = to_ruby<uint>(k);
        return h;
    }
#endif
};

I can use to_h() to easily convert to a Ruby type, but my understanding is
there's a way to do it automatically.

Additionally, I have this little gem elsewhere in my code:
DistanceMatrix::DistanceMatrix(const Array& source_matrix_ids, Rice::Object
classifier_params_h)
    // Convert from Hash to cparams
    cparams classifier_params(
from_ruby<Rice::Symbol>(classifier_params_h.call("fetch",
Rice::Symbol("classifier"))).str() );
    classifier_params.k = from_ruby<uint>(classifier_params_h.call("fetch",
Rice::Symbol("k")));
    // ...

Ack! How would I write a from_ruby handler for something like this? Perhaps
you've got an example somewhere that I just haven't been able to find?

Perhaps you could add it to the FAQ? I see the theoretical explanation of
from_ruby and to_ruby, but I don't know enough about the C side of Ruby --
or Rice for that matter -- to grok it.

Many thanks,
John

Re: [rice] from_ruby on complex types (and to_ruby)

From:
Jason Roelofs
Date:
2010-05-28 @ 12:03
First, you're right I definitely need to get some better documentation on 
to_/from_ruby, it can be a hard construct to understand at first.

As for your case, you've pretty much got what you would need to put in a 
to_ruby or from_ruby construct for your wrapper to work. 

Given your to_h method, your to_ruby would simply look like (off the top 
of my head):

Rice::Object to_ruby(cparams const & param) {
  return param.to_h();
}

And then you can use Rice::Hash to make your from_ruby a bit cleaner:

cparams from_ruby<cparams>(Rice::Object x) {
  Rice::Hash hash(x);
  cparams params( hash[ Rice::Symbol("classifier") ].str() );
  params.k = from_ruby<uint>(hash[Rice::Symbol("k")]);

  return params;
}

Let me know if this works / doesn't work.

Jason


On May 27, 2010, at 3:07 PM, John O. Woods wrote:

> I'm not quite clear how to implement from_ruby for different complex 
types in C++.
> 
> For example, right now, I have this object that should be really easy to
turn into an :options => {:symbol => true, :other_symbol => false} type of
hash (as used in Rails).
> 
> using std::string;
> class cparams {
> public:
>     cparams(const string& name) : classifier(name), k(0) { }
> 
>     string classifier;
>     uint k;
> 
> #ifdef RICE
>     Rice::Object to_h() const {
>         Rice::Hash h;
>         h[ Rice::Symbol("classifier")   ]   = to_ruby<string>(classifier);
>         if (k > 0) h[ Rice::Symbol("k") ]   = to_ruby<uint>(k);        
>         return h;
>     }
> #endif
> };
> 
> I can use to_h() to easily convert to a Ruby type, but my understanding 
is there's a way to do it automatically.
> 
> Additionally, I have this little gem elsewhere in my code:
> DistanceMatrix::DistanceMatrix(const Array& source_matrix_ids, 
Rice::Object classifier_params_h)
>     // Convert from Hash to cparams
>     cparams classifier_params( 
from_ruby<Rice::Symbol>(classifier_params_h.call("fetch", 
Rice::Symbol("classifier"))).str() );
>     classifier_params.k = 
from_ruby<uint>(classifier_params_h.call("fetch", Rice::Symbol("k")));
>     // ...
> 
> Ack! How would I write a from_ruby handler for something like this? 
Perhaps you've got an example somewhere that I just haven't been able to 
find?
> 
> Perhaps you could add it to the FAQ? I see the theoretical explanation 
of from_ruby and to_ruby, but I don't know enough about the C side of Ruby
-- or Rice for that matter -- to grok it.
> 
> Many thanks,
> John

Re: [rice] from_ruby on complex types (and to_ruby)

From:
John O. Woods
Date:
2010-05-28 @ 16:29
That example definitely works, but I'm having more trouble with
std::set<uint>.

For example, I have a member function:

void push_mask(const set<uint>& mask_rows);

It's exposed to Ruby with:
 .define_method("push_mask", &PhenomatrixPair::push_mask)

And I have a from_ruby written:

// Convert from Rice::Array to std::set
std::set<uint> from_ruby(Rice::Object x) {
    Rice::Array ary(x);
    std::set<uint> result;
    for (Rice::Array::iterator i = ary.begin(); i != ary.end(); ++i)
        result.insert(from_ruby<uint>(*i));
    return result;
}

Compilation works fine, but when I try to run the tests, I get an error:

  1) Error:
test_push_and_pop_mask(TestPhenomatrixExtn):
ArgumentError: Unable to convert Array to std::set<unsigned int,
std::less<unsigned int>, std::allocator<unsigned int> >*
    ./test/test_phenomatrix_pair_extn.rb:26:in `push_mask'
    ./test/test_phenomatrix_pair_extn.rb:26:in `test_push_and_pop_mask'

I've seen an error like this before when I forgot to put a *using namespace
rice;* in my cpp file -- since it's a C extern. Is that the problem?

Incidentally, do you all have a donations page?

Thanks again,
John




On Fri, May 28, 2010 at 7:03 AM, Jason Roelofs <jameskilton@gmail.com>wrote:

> First, you're right I definitely need to get some better documentation on
> to_/from_ruby, it can be a hard construct to understand at first.
>
> As for your case, you've pretty much got what you would need to put in a
> to_ruby or from_ruby construct for your wrapper to work.
>
> Given your to_h method, your to_ruby would simply look like (off the top of
> my head):
>
> Rice::Object to_ruby(cparams const & param) {
>  return param.to_h();
> }
>
> And then you can use Rice::Hash to make your from_ruby a bit cleaner:
>
> cparams from_ruby<cparams>(Rice::Object x) {
>  Rice::Hash hash(x);
>  cparams params( hash[ Rice::Symbol("classifier") ].str() );
>  params.k = from_ruby<uint>(hash[Rice::Symbol("k")]);
>
>  return params;
> }
>
> Let me know if this works / doesn't work.
>
> Jason
>
>
> On May 27, 2010, at 3:07 PM, John O. Woods wrote:
>
> > I'm not quite clear how to implement from_ruby for different complex
> types in C++.
> >
> > For example, right now, I have this object that should be really easy to
> turn into an :options => {:symbol => true, :other_symbol => false} type of
> hash (as used in Rails).
> >
> > using std::string;
> > class cparams {
> > public:
> >     cparams(const string& name) : classifier(name), k(0) { }
> >
> >     string classifier;
> >     uint k;
> >
> > #ifdef RICE
> >     Rice::Object to_h() const {
> >         Rice::Hash h;
> >         h[ Rice::Symbol("classifier")   ]   =
> to_ruby<string>(classifier);
> >         if (k > 0) h[ Rice::Symbol("k") ]   = to_ruby<uint>(k);
> >         return h;
> >     }
> > #endif
> > };
> >
> > I can use to_h() to easily convert to a Ruby type, but my understanding
> is there's a way to do it automatically.
> >
> > Additionally, I have this little gem elsewhere in my code:
> > DistanceMatrix::DistanceMatrix(const Array& source_matrix_ids,
> Rice::Object classifier_params_h)
> >     // Convert from Hash to cparams
> >     cparams classifier_params(
> from_ruby<Rice::Symbol>(classifier_params_h.call("fetch",
> Rice::Symbol("classifier"))).str() );
> >     classifier_params.k =
> from_ruby<uint>(classifier_params_h.call("fetch", Rice::Symbol("k")));
> >     // ...
> >
> > Ack! How would I write a from_ruby handler for something like this?
> Perhaps you've got an example somewhere that I just haven't been able to
> find?
> >
> > Perhaps you could add it to the FAQ? I see the theoretical explanation of
> from_ruby and to_ruby, but I don't know enough about the C side of Ruby --
> or Rice for that matter -- to grok it.
> >
> > Many thanks,
> > John
>
>

Re: [rice] from_ruby on complex types (and to_ruby)

From:
Jason Roelofs
Date:
2010-05-28 @ 16:52
I'm guessing C++ simply isn't finding your from_ruby definition, you need 
to specify the template explicitly (return types don't work like 
parameters do):

std::set<uint> from_ruby< std::set<uint> >(Rice::Object x)

Also, I did forget to mention that the true prototype of these functions 
are actually:

Rice::Object Rice::to_ruby<Type>(Type const & x)

Type Rice::from_ruby<Type>(Rice::Object x)

which is why your "using namespace Rice" makes a difference. Sorry about that.

As for donations, I appreciate the offer but don't have plans on opening 
up donations to the project at this time. 

Jason

On May 28, 2010, at 12:29 PM, John O. Woods wrote:

> That example definitely works, but I'm having more trouble with std::set<uint>.
> 
> For example, I have a member function:
> 
> void push_mask(const set<uint>& mask_rows);
> 
> It's exposed to Ruby with:
>  .define_method("push_mask", &PhenomatrixPair::push_mask)
> 
> And I have a from_ruby written:
> 
> // Convert from Rice::Array to std::set
> std::set<uint> from_ruby(Rice::Object x) {
>     Rice::Array ary(x);
>     std::set<uint> result;
>     for (Rice::Array::iterator i = ary.begin(); i != ary.end(); ++i)
>         result.insert(from_ruby<uint>(*i));
>     return result;
> }
> 
> Compilation works fine, but when I try to run the tests, I get an error:
> 
>   1) Error:
> test_push_and_pop_mask(TestPhenomatrixExtn):
> ArgumentError: Unable to convert Array to std::set<unsigned int, 
std::less<unsigned int>, std::allocator<unsigned int> >*
>     ./test/test_phenomatrix_pair_extn.rb:26:in `push_mask'
>     ./test/test_phenomatrix_pair_extn.rb:26:in `test_push_and_pop_mask'
> 
> I've seen an error like this before when I forgot to put a using 
namespace rice; in my cpp file -- since it's a C extern. Is that the 
problem?
> 
> Incidentally, do you all have a donations page?
> 
> Thanks again,
> John
> 
> 
> 
> 
> On Fri, May 28, 2010 at 7:03 AM, Jason Roelofs <jameskilton@gmail.com> wrote:
> First, you're right I definitely need to get some better documentation 
on to_/from_ruby, it can be a hard construct to understand at first.
> 
> As for your case, you've pretty much got what you would need to put in a
to_ruby or from_ruby construct for your wrapper to work.
> 
> Given your to_h method, your to_ruby would simply look like (off the top
of my head):
> 
> Rice::Object to_ruby(cparams const & param) {
>  return param.to_h();
> }
> 
> And then you can use Rice::Hash to make your from_ruby a bit cleaner:
> 
> cparams from_ruby<cparams>(Rice::Object x) {
>  Rice::Hash hash(x);
>  cparams params( hash[ Rice::Symbol("classifier") ].str() );
>  params.k = from_ruby<uint>(hash[Rice::Symbol("k")]);
> 
>  return params;
> }
> 
> Let me know if this works / doesn't work.
> 
> Jason
> 
> 
> On May 27, 2010, at 3:07 PM, John O. Woods wrote:
> 
> > I'm not quite clear how to implement from_ruby for different complex 
types in C++.
> >
> > For example, right now, I have this object that should be really easy 
to turn into an :options => {:symbol => true, :other_symbol => false} type
of hash (as used in Rails).
> >
> > using std::string;
> > class cparams {
> > public:
> >     cparams(const string& name) : classifier(name), k(0) { }
> >
> >     string classifier;
> >     uint k;
> >
> > #ifdef RICE
> >     Rice::Object to_h() const {
> >         Rice::Hash h;
> >         h[ Rice::Symbol("classifier")   ]   = to_ruby<string>(classifier);
> >         if (k > 0) h[ Rice::Symbol("k") ]   = to_ruby<uint>(k);
> >         return h;
> >     }
> > #endif
> > };
> >
> > I can use to_h() to easily convert to a Ruby type, but my 
understanding is there's a way to do it automatically.
> >
> > Additionally, I have this little gem elsewhere in my code:
> > DistanceMatrix::DistanceMatrix(const Array& source_matrix_ids, 
Rice::Object classifier_params_h)
> >     // Convert from Hash to cparams
> >     cparams classifier_params( 
from_ruby<Rice::Symbol>(classifier_params_h.call("fetch", 
Rice::Symbol("classifier"))).str() );
> >     classifier_params.k = 
from_ruby<uint>(classifier_params_h.call("fetch", Rice::Symbol("k")));
> >     // ...
> >
> > Ack! How would I write a from_ruby handler for something like this? 
Perhaps you've got an example somewhere that I just haven't been able to 
find?
> >
> > Perhaps you could add it to the FAQ? I see the theoretical explanation
of from_ruby and to_ruby, but I don't know enough about the C side of Ruby
-- or Rice for that matter -- to grok it.
> >
> > Many thanks,
> > John
> 
> 

Re: [rice] from_ruby on complex types (and to_ruby)

From:
John O. Woods
Date:
2010-05-28 @ 18:26
I was able to get it, finally, with one caveat.

For this code:

// Convert from Rice::Array to std::set
template <>
std::set<uint> from_ruby<std::set<uint> >(Rice::Object x) {
    Rice::Array ary(x);
    std::set<uint> result;
    for (Rice::Array::iterator i = ary.begin(); i != ary.end(); ++i)
        result.insert(Rice::from_ruby<uint>(*i)); // THIS LINE
    return result;
}

I get an error:

In file included from ../../../../ext/phenomatrix/id_dist.cpp:38:
../../../../ext/phenomatrix/ruby_conversions.h: In function ‘typename
Rice::detail::from_ruby_<T>::Retval_T from_ruby(Rice::Object) [with T =
std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned int>
>]’:
../../../../ext/phenomatrix/ruby_conversions.h:23: error: ‘from_ruby’ is not
a member of ‘Rice’
../../../../ext/phenomatrix/ruby_conversions.h:23: error: expected
primary-expression before ‘>’ token

It works fine if I remove the Rice::, for whatever reason. (I'm also using
namespace rice now).

While I've got you on the line, here's a related question -- what if I were
dealing with a Ruby set instead of a Ruby array? There's obviously a
Rice::Array type, but how would one go about dealing with set? I suppose you
could call to_a on the object, but I'm guessing there'd be a more efficient
way to convert from Ruby set to std::set than through Rice::Array.

This is a purely hypothetical question. Please don't trouble yourself with
it -- I was just wondering if you have an example handy, or could point me
toward some resource.

John

On Fri, May 28, 2010 at 11:52 AM, Jason Roelofs <jameskilton@gmail.com>wrote:

> I'm guessing C++ simply isn't finding your from_ruby definition, you need
> to specify the template explicitly (return types don't work like parameters
> do):
>
> std::set<uint> from_ruby< std::set<uint> >(Rice::Object x)
>
> Also, I did forget to mention that the true prototype of these functions
> are actually:
>
> Rice::Object Rice::to_ruby<Type>(Type const & x)
>
> Type Rice::from_ruby<Type>(Rice::Object x)
>
> which is why your "using namespace Rice" makes a difference. Sorry about
> that.
>
> As for donations, I appreciate the offer but don't have plans on opening up
> donations to the project at this time.
>
> Jason
>
> On May 28, 2010, at 12:29 PM, John O . Woods wrote:
>
> That example definitely works, but I'm having more trouble with
> std::set<uint>.
>
> For example, I have a member function:
>
> void push_mask(const set<uint>& mask_rows);
>
> It's exposed to Ruby with:
>  .define_method("push_mask", &PhenomatrixPair::push_mask)
>
> And I have a from_ruby written:
>
> // Convert from Rice::Array to std::set
> std::set<uint> from_ruby(Rice::Object x) {
>     Rice::Array ary(x);
>     std::set<uint> result;
>     for (Rice::Array::iterator i = ary.begin(); i != ary.end(); ++i)
>         result.insert(from_ruby<uint>(*i));
>     return result;
> }
>
> Compilation works fine, but when I try to run the tests, I get an error:
>
>   1) Error:
> test_push_and_pop_mask(TestPhenomatrixExtn):
> ArgumentError: Unable to convert Array to std::set<unsigned int,
> std::less<unsigned int>, std::allocator<unsigned int> >*
>     ./test/test_phenomatrix_pair_extn.rb:26:in `push_mask'
>     ./test/test_phenomatrix_pair_extn.rb:26:in `test_push_and_pop_mask'
>
> I've seen an error like this before when I forgot to put a *using
> namespace rice;* in my cpp file -- since it's a C extern. Is that the
> problem?
>
> Incidentally, do you all have a donations page?
>
> Thanks again,
> John
>
>
>
>
> On Fri, May 28, 2010 at 7:03 AM, Jason Roelofs <jameskilton@gmail.com>wrote:
>
>> First, you're right I definitely need to get some better documentation on
>> to_/from_ruby, it can be a hard construct to understand at first.
>>
>> As for your case, you've pretty much got what you would need to put in a
>> to_ruby or from_ruby construct for your wrapper to work.
>>
>> Given your to_h method, your to_ruby would simply look like (off the top
>> of my head):
>>
>> Rice::Object to_ruby(cparams const & param) {
>>  return param.to_h();
>> }
>>
>> And then you can use Rice::Hash to make your from_ruby a bit cleaner:
>>
>> cparams from_ruby<cparams>(Rice::Object x) {
>>  Rice::Hash hash(x);
>>  cparams params( hash[ Rice::Symbol("classifier") ].str() );
>>  params.k = from_ruby<uint>(hash[Rice::Symbol("k")]);
>>
>>  return params;
>> }
>>
>> Let me know if this works / doesn't work.
>>
>> Jason
>>
>>
>> On May 27, 2010, at 3:07 PM, John O. Woods wrote:
>>
>> > I'm not quite clear how to implement from_ruby for different complex
>> types in C++.
>> >
>> > For example, right now, I have this object that should be really easy to
>> turn into an :options => {:symbol => true, :other_symbol => false} type of
>> hash (as used in Rails).
>> >
>> > using std::string;
>> > class cparams {
>> > public:
>> >     cparams(const string& name) : classifier(name), k(0) { }
>> >
>> >     string classifier;
>> >     uint k;
>> >
>> > #ifdef RICE
>> >     Rice::Object to_h() const {
>> >         Rice::Hash h;
>> >         h[ Rice::Symbol("classifier")   ]   =
>> to_ruby<string>(classifier);
>> >         if (k > 0) h[ Rice::Symbol("k") ]   = to_ruby<uint>(k);
>> >         return h;
>> >     }
>> > #endif
>> > };
>> >
>> > I can use to_h() to easily convert to a Ruby type, but my understanding
>> is there's a way to do it automatically.
>> >
>> > Additionally, I have this little gem elsewhere in my code:
>> > DistanceMatrix::DistanceMatrix(const Array& source_matrix_ids,
>> Rice::Object classifier_params_h)
>> >     // Convert from Hash to cparams
>> >     cparams classifier_params(
>> from_ruby<Rice::Symbol>(classifier_params_h.call("fetch",
>> Rice::Symbol("classifier"))).str() );
>> >     classifier_params.k =
>> from_ruby<uint>(classifier_params_h.call("fetch", Rice::Symbol("k")));
>> >     // ...
>> >
>> > Ack! How would I write a from_ruby handler for something like this?
>> Perhaps you've got an example somewhere that I just haven't been able to
>> find?
>> >
>> > Perhaps you could add it to the FAQ? I see the theoretical explanation
>> of from_ruby and to_ruby, but I don't know enough about the C side of Ruby
>> -- or Rice for that matter -- to grok it.
>> >
>> > Many thanks,
>> > John
>>
>>
>
>

Re: [rice] from_ruby on complex types (and to_ruby)

From:
Jason Roelofs
Date:
2010-05-28 @ 18:39
Derp, I was wrong about being wrong.... The to_ruby and from_ruby methods 
are *not* a member of the Rice namespace. Must be Friday...

To answer your question, I would recommend turning it into an Array and 
going from there:

Rice::Array arr(x.call("to_a"));

I have in the plans to build a proper way to let Rice deal with the 
nastiness of defining conversions from Ruby types to STL containers, but 
it's not going to be ready for a while, so this is the best answer I have 
for you, especially given Set is implemented in pure Ruby.

Jason

On May 28, 2010, at 2:26 PM, John O. Woods wrote:

> I was able to get it, finally, with one caveat.
> 
> For this code:
> 
> // Convert from Rice::Array to std::set
> template <>
> std::set<uint> from_ruby<std::set<uint> >(Rice::Object x) {
>     Rice::Array ary(x);
>     std::set<uint> result;
>     for (Rice::Array::iterator i = ary.begin(); i != ary.end(); ++i)
>         result.insert(Rice::from_ruby<uint>(*i)); // THIS LINE
>     return result;
> }
> 
> I get an error:
> 
> In file included from ../../../../ext/phenomatrix/id_dist.cpp:38:
> ../../../../ext/phenomatrix/ruby_conversions.h: In function ‘typename 
Rice::detail::from_ruby_<T>::Retval_T from_ruby(Rice::Object) [with T = 
std::set<unsigned int, std::less<unsigned int>, std::allocator<unsigned 
int> >]’:
> ../../../../ext/phenomatrix/ruby_conversions.h:23: error: ‘from_ruby’ is
not a member of ‘Rice’
> ../../../../ext/phenomatrix/ruby_conversions.h:23: error: expected 
primary-expression before ‘>’ token
> 
> It works fine if I remove the Rice::, for whatever reason. (I'm also 
using namespace rice now).
> 
> While I've got you on the line, here's a related question -- what if I 
were dealing with a Ruby set instead of a Ruby array? There's obviously a 
Rice::Array type, but how would one go about dealing with set? I suppose 
you could call to_a on the object, but I'm guessing there'd be a more 
efficient way to convert from Ruby set to std::set than through 
Rice::Array.
> 
> This is a purely hypothetical question. Please don't trouble yourself 
with it -- I was just wondering if you have an example handy, or could 
point me toward some resource.
> 
> John
> 
> On Fri, May 28, 2010 at 11:52 AM, Jason Roelofs <jameskilton@gmail.com> wrote:
> I'm guessing C++ simply isn't finding your from_ruby definition, you 
need to specify the template explicitly (return types don't work like 
parameters do):
> 
> std::set<uint> from_ruby< std::set<uint> >(Rice::Object x)
> 
> Also, I did forget to mention that the true prototype of these functions
are actually:
> 
> Rice::Object Rice::to_ruby<Type>(Type const & x)
> 
> Type Rice::from_ruby<Type>(Rice::Object x)
> 
> which is why your "using namespace Rice" makes a difference. Sorry about that.
> 
> As for donations, I appreciate the offer but don't have plans on opening
up donations to the project at this time. 
> 
> Jason
> 
> On May 28, 2010, at 12:29 PM, John O . Woods wrote:
> 
>> That example definitely works, but I'm having more trouble with std::set<uint>.
>> 
>> For example, I have a member function:
>> 
>> void push_mask(const set<uint>& mask_rows);
>> 
>> It's exposed to Ruby with:
>>  .define_method("push_mask", &PhenomatrixPair::push_mask)
>> 
>> And I have a from_ruby written:
>> 
>> // Convert from Rice::Array to std::set
>> std::set<uint> from_ruby(Rice::Object x) {
>>     Rice::Array ary(x);
>>     std::set<uint> result;
>>     for (Rice::Array::iterator i = ary.begin(); i != ary.end(); ++i)
>>         result.insert(from_ruby<uint>(*i));
>>     return result;
>> }
>> 
>> Compilation works fine, but when I try to run the tests, I get an error:
>> 
>>   1) Error:
>> test_push_and_pop_mask(TestPhenomatrixExtn):
>> ArgumentError: Unable to convert Array to std::set<unsigned int, 
std::less<unsigned int>, std::allocator<unsigned int> >*
>>     ./test/test_phenomatrix_pair_extn.rb:26:in `push_mask'
>>     ./test/test_phenomatrix_pair_extn.rb:26:in `test_push_and_pop_mask'
>> 
>> I've seen an error like this before when I forgot to put a using 
namespace rice; in my cpp file -- since it's a C extern. Is that the 
problem?
>> 
>> Incidentally, do you all have a donations page?
>> 
>> Thanks again,
>> John
>> 
>> 
>> 
>> 
>> On Fri, May 28, 2010 at 7:03 AM, Jason Roelofs <jameskilton@gmail.com> wrote:
>> First, you're right I definitely need to get some better documentation 
on to_/from_ruby, it can be a hard construct to understand at first.
>> 
>> As for your case, you've pretty much got what you would need to put in 
a to_ruby or from_ruby construct for your wrapper to work.
>> 
>> Given your to_h method, your to_ruby would simply look like (off the 
top of my head):
>> 
>> Rice::Object to_ruby(cparams const & param) {
>>  return param.to_h();
>> }
>> 
>> And then you can use Rice::Hash to make your from_ruby a bit cleaner:
>> 
>> cparams from_ruby<cparams>(Rice::Object x) {
>>  Rice::Hash hash(x);
>>  cparams params( hash[ Rice::Symbol("classifier") ].str() );
>>  params.k = from_ruby<uint>(hash[Rice::Symbol("k")]);
>> 
>>  return params;
>> }
>> 
>> Let me know if this works / doesn't work.
>> 
>> Jason
>> 
>> 
>> On May 27, 2010, at 3:07 PM, John O. Woods wrote:
>> 
>> > I'm not quite clear how to implement from_ruby for different complex 
types in C++.
>> >
>> > For example, right now, I have this object that should be really easy
to turn into an :options => {:symbol => true, :other_symbol => false} type
of hash (as used in Rails).
>> >
>> > using std::string;
>> > class cparams {
>> > public:
>> >     cparams(const string& name) : classifier(name), k(0) { }
>> >
>> >     string classifier;
>> >     uint k;
>> >
>> > #ifdef RICE
>> >     Rice::Object to_h() const {
>> >         Rice::Hash h;
>> >         h[ Rice::Symbol("classifier")   ]   = to_ruby<string>(classifier);
>> >         if (k > 0) h[ Rice::Symbol("k") ]   = to_ruby<uint>(k);
>> >         return h;
>> >     }
>> > #endif
>> > };
>> >
>> > I can use to_h() to easily convert to a Ruby type, but my 
understanding is there's a way to do it automatically.
>> >
>> > Additionally, I have this little gem elsewhere in my code:
>> > DistanceMatrix::DistanceMatrix(const Array& source_matrix_ids, 
Rice::Object classifier_params_h)
>> >     // Convert from Hash to cparams
>> >     cparams classifier_params( 
from_ruby<Rice::Symbol>(classifier_params_h.call("fetch", 
Rice::Symbol("classifier"))).str() );
>> >     classifier_params.k = 
from_ruby<uint>(classifier_params_h.call("fetch", Rice::Symbol("k")));
>> >     // ...
>> >
>> > Ack! How would I write a from_ruby handler for something like this? 
Perhaps you've got an example somewhere that I just haven't been able to 
find?
>> >
>> > Perhaps you could add it to the FAQ? I see the theoretical 
explanation of from_ruby and to_ruby, but I don't know enough about the C 
side of Ruby -- or Rice for that matter -- to grok it.
>> >
>> > Many thanks,
>> > John
>> 
>> 
> 
>