Forum: Ruby A C++ reference in a Ruby extension

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
David Simas (Guest)
on 2007-04-12 05:09
(Received via mailing list)
I'm trying to write an extension to access some C++ libraries from
Ruby (1.8.4).  One of the C++ functions uses a reference to pass
a value back to the caller as a side effect:

   ErrorHandle* DetectInvisibleWatermark(const char *inputfilename,
          const char *wmfilename,
          float horizOffset,
          float vertOffset,
          float lowPassFilterFactor,
                 float &modulationStrength,
          const char *key, const char *seed,
          const char *outfilename);

(N.B.: "float &modulationStrength")

Any suggestions on how to handle this reference in an extension?
I don't have the C++ sources, just libraries and header files.

Thanks,

DGS
Logan C. (Guest)
on 2007-04-12 07:37
(Received via mailing list)
On Thu, Apr 12, 2007 at 10:07:52AM +0900, David Simas wrote:
>           float lowPassFilterFactor,
>                  float &modulationStrength,
>           const char *key, const char *seed,
>           const char *outfilename);
>
> (N.B.: "float &modulationStrength")
Wrap it in a C function
void foo(float* bar) {
   baz(*bar);
}

void baz(float& quux) {
  quux /= 1.5;
}
Joel VanderWerf (Guest)
on 2007-04-12 09:16
(Received via mailing list)
Logan C. wrote:
>>           float lowPassFilterFactor,
> void baz(float& quux) {
>   quux /= 1.5;
> }

There's still the question of how to get both return values back to the
caller. It depends on how you want to use the function from ruby. You
could return both the ErrorHandle and a float, as a two element array (a
ruby array, that is). The caller can then unpack them like this:

err_h, mod_str = wrap_DetectInvisibleWatermark(...)

Or you could return one and yield the other (a good choice if one is
less likely to be used).

Or maybe return the float (as a ruby float, of course) and rb_raise() if
there is a nonzero ErrorHandle* .
Paul B. (Guest)
on 2007-04-12 18:01
(Received via mailing list)
On Thu, Apr 12, 2007 at 10:07:52AM +0900, David Simas wrote:
>           float lowPassFilterFactor,
>                  float &modulationStrength,
>           const char *key, const char *seed,
>           const char *outfilename);
>
> (N.B.: "float &modulationStrength")
>
> Any suggestions on how to handle this reference in an extension?
> I don't have the C++ sources, just libraries and header files.

In general, there are two options for handling out parameters:

1. Treat them as additional return values (so effectively you have
   "return a, b" instead of "return a") - this is less consistent with
   the C++ interface but is easy to use

2. Box the value so it can be modified (so for modulationStrength you'd
   pass in Box.new, then get modulationStrength out of the Box) - this
   is more consistent with the C++ interface but IMO is harder to use

But in this case you are using a return value for error handling.  I'd
raise an exception instead of returning error values.

As an aside, in general, returning errors in C++ is a bad idea, because
C++ doesn't provide a good mechanism for returning failure from a
constructor other than an exception.  It's usually better to be
consistent and use exceptions everywhere, rather than only where you
need them.

Paul
This topic is locked and can not be replied to.