Returning a reference to an existing C++ object as a reference

J

JustMe

Hi All,

Given:

package x;

sub new { return bless {}, $_[0]; }

#-- callback() is call by the C++ class (reader_as_cpp_object)
#-- whenever an event is detected.

sub callback {
my ($self, $ref_to_an_event_object) = @_;
print $ref_to_an_event_object->data();
}

package main;

use reader_as_cpp_object;

my $x = x->new();
my $reader = reader_as_cpp_object->new($x)

$reader->read( 'afile.txt' ) # Reader is a reference to a C++ class


I've got the callback working just fine. The problem I can't seem to
solve, is how to pass the sub callback() a reference to a C++ object
that was created by the C++ object reader_as_cpp_object.

All of the examples I've seen assume that object is create via an
action from the perl program. E.g.

my $object = cow->new();


I've read perlgut, perlapi, perlxs, perlxstut, cookbookA and
cookbookB, and googled all day and I'm still no closer to a solution.

Anyone have an example and or suggestion?

Thanks

Eric
 
T

Tassilo v. Parseval

Also sprach JustMe:
Given:

package x;

sub new { return bless {}, $_[0]; }

#-- callback() is call by the C++ class (reader_as_cpp_object)
#-- whenever an event is detected.

sub callback {
my ($self, $ref_to_an_event_object) = @_;
print $ref_to_an_event_object->data();
}

package main;

use reader_as_cpp_object;

my $x = x->new();
my $reader = reader_as_cpp_object->new($x)

$reader->read( 'afile.txt' ) # Reader is a reference to a C++ class


I've got the callback working just fine. The problem I can't seem to
solve, is how to pass the sub callback() a reference to a C++ object
that was created by the C++ object reader_as_cpp_object.

Can you be more specific? You want $ref_to_an_event_object to
contain a pointer to a C++ object? This is easy. Do something like this
in your callback:

OBJECT *obj; // obj is the C++ object

...
SV *ref_to_obj = sv_newmortal();
sv_setref_pv(ref_to_object, "Class::Of::Reader", (void*)obj);

XPUSHs(ref_to_object); // push onto stack to pass to Perl callback
...

Your callback will now receive a scalar variable with an integer in it.
This integer is the address of the C++ object. To de-reference the
pointer and get the object back, you do:

OBJECT *obj = (OBJECT*)SvIV((SV*)SvRV(ref_to_object));

Usually, you put such things into a typemap file to let these
conversions happen authomatically:

# mapping from C++ objects to INPUT/OUTPUT objects
OBJECT * O_OBJECT

OUTPUT
O_OBJECT
sv_setref_pv( $arg, CLASS, (void*)$var );

INPUT
O_OBJECT
if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
$var = ($type)SvIV((SV*)SvRV( $arg ));
else{
warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" );
XSRETURN_UNDEF;
}

And now you can use that in your XSUBS very conveniently:

OBJECT *
function (obj)
OBJECT *obj;
PREINIT:
OBJECT *new_object;
CODE:
...
new_object = new OBJECT (args,...);
RETVAL = new_object;
OUTPUT:
RETVAL

So INPUT typemap kicks in when you pass your XSUB an appropriate
argument. 'OBJECT *obj' is such an argument and now Perl will convert
the SV* it receives into a pointer to OBJECT according to the
INPUT/O_OBJECT typemap. When returning 'OBJECT*', OUTPUT/O_OBJECT turns
a C++ object into a SV*.

When calling a Perl-callback however, you have to do this conversion
manually as I showed further above. You just copy the pointer (casted to
(void*) into an SV using sv_setref_pv(), at the same time blessing the
scalar variable into the appropriate package that should handle objects
of this type. Since your function read() operates on the C++ object,
bless it into the package where this method is defined. Use the INPUT
there and your Perl object is turned into a C++ again.
I've read perlgut, perlapi, perlxs, perlxstut, cookbookA and
cookbookB, and googled all day and I'm still no closer to a solution.

I was just about to recommend cookbookA and cookbookB, but you have
already read that. It's not exactly full of verbose explanations, it
just gives a few examples. Do they make more sense now? You could try to
re-read perlxs.pod, section "Using XS with C++".

Tassilo
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,293
Messages
2,571,505
Members
48,192
Latest member
LinwoodFol

Latest Threads

Top