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

Discussion in 'Perl Misc' started by JustMe, Aug 29, 2003.

  1. JustMe

    JustMe Guest

    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
    JustMe, Aug 29, 2003
    #1
    1. Advertising

  2. 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
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
    Tassilo v. Parseval, Aug 29, 2003
    #2
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andrew Purser
    Replies:
    3
    Views:
    406
    Andrew Purser
    Jul 26, 2004
  2. PGR
    Replies:
    6
    Views:
    392
    Stefan Ram
    Jan 4, 2006
  3. nrm
    Replies:
    3
    Views:
    527
  4. Replies:
    1
    Views:
    476
    Mark Rae [MVP]
    Sep 20, 2007
  5. Replies:
    0
    Views:
    185
Loading...

Share This Page