On Mon, Mar 01, 2004 at 02:19:53AM +0300 Vadim O. Ustiansky wrote:

> I am new to XS and have not found the solution to my
> problem in either docs or CPAN modules' sources so far.
> 
> I want to implement a perl object as a hash reference
> but I want some functionality to be implemented in C
> which requires to bind some C struct with this perl
> object. The question is how this can be accomplished.
> The obvious solution (storing a pointer to the struct
> as one of the hash's value) has the obvious objection:
> anyone has access to this value at perl level as
>   $obj->{key} = "whatever";
> or even
>   delete($obj->{key});
> 
> Nevertheless the CPAN modules I investigated use either
> this approach or they implement all functionality in C.
> In the latter case the object is implemented as a reference
> to a scalar which holds memory address so perl code like:
>   $$obj = 0x12345;
> may break up all the internal C implementation.
> 
> So my question is whether it is possible to completely hide
> C internals from perl level.

Sure it is. You can do it manually:

    void
    new (CLASS, ...) 
            char *CLASS;
        CODE:
        {
            c_struct *var;
            New(0, var, c_struct, sizeof(c_struct));
            ...
            ST(0) = sv_newmortal();
            sv_setref_pv(ST(0), CLASS, (void*)var);
            XSRETURN(1);
        }

This returns a blessed Perl reference (blessed into class CLASS).
Dereferencing can be done thusly:

    void
    method (obj)
            SV *obj;
        CODE:
        {
            c_struct *var = (c_struct*)SvIV(SvREF(ovj));
            ...
        }

It's more convenient to do that via typemaps. I think you can use the
predefined T_PTROBJ for that. Put this into the file typemap:

    c_struct *      T_PTROBJ

This simplifies your XS to

    c_struct *
    new (...)
        CODE:
        {
            c_struct *var;
            ...
            RETVAL = var;
        }
        OUTPUT:
            RETVAL

And for input:
    
    void
    method (self) 
            c_struct *self;
        CODE:
            ...

The typemap file is just a sort of text template that is processed by
xsubpp. The idea is always the same. You take the address of a C
structure and store it somewhere in an SV, for instance the IV slot.
This happens through ordinary C typecasts.

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

Reply via email to