Hi Nick,

Nick Ing-Simmons wrote:

Tim Pushor <[EMAIL PROTECTED]> writes:


You are right, that was not a very good way of going about it. I felt that from the start, but this code is ISAM database code, and the variable in question is the block pointer. This pointer gets updated every time an ISAM operation is done - which is at least once for each record scanned/loaded. I wanted to avoid copying variables back and forth on each ISAM operation, for more efficiency.



The "Subject:" vesion can be done, but is a bit messy.
The problem is making sure the lifetime of the shared thing is long enough fro both C and perl.


What Tk does for a few "global" C vars like this is declare & define them as
C. Then create perl proxies for them with XS code to provide FETCH and STORE
of a 'tie'. So when perl goes for $foo it calls Module::FETCH which is XS code which grabs the C variable and puts in in a perl SV and returns it.
Or Module::STORE which gets value from perl and writes it to the C variable.
This scheme is more robust than having C code use SvNV slot of some perl SV. The latter can be done, but SV probably needs is SvREFCNT incrementing to make sure it stays about. Main snag with that and double
(in particular) is that say:


  $var = 3;

_May_ not set NV at all, but the IV slot. And $var = '3';
is even worse. The 'tie' scheme give your XS code a hook to force conversion to C's type.




I can see your point. The tie scheme looks like a clean way to implement what I was trying to do in the first place. For now, what I am doing is taking a reference to a scalar, then in the C functions, before I use the double, I take the value of the scalar, stuff it in the double, then after the C operation put it back into the scalar. The only problem with this is that I don't really understand how the reference count stuff really works in perl. I have a feeling that since I am holding onto the reference (actually, I am not - I found that this didn't work for some reason) I need to bump the reference count.

So now come to think of it, what I am really doing is storing the value of the scalar itself, like:

Perl:

$key=1; store (\$key);

print "$key\n";

cfunc();

print "$key\n";

C:

/* Global */

SV *perlvar;

void store (SV *ref) {
   perlvar=SvRV(ref);
}

void cfunc (double val) {
   sv_setnv(perlvar,val);
}

* When I tried to save the reference in a global and access it later it didn't work. Is this becuase I didin't bump the reference count? What are the downsides to the way I am doing it now (I *know* there must be a downside).

However collecting things in to an "execution context" as suggested is likely to be cleaner.



I don't really follow that.

A clean scheme is put a C "struct" in the string slot of an SV.
If this is just opaque data that is all you need to do, and perls REFCNT will free string at right time.


To get at sub-fields from perl side with provide XS "methods" as accessors
or (if struct isn't too complex) accessors in perl code that use pack/unpack on the data.




I think this may be overkill.

I really like your TIE idea. Mostly because there is nothing special to do on the C side, where I really need the performance. From perl, I can call the isam routine repeatedly and there is no copying the double in and out of the perl scalar. Now if I could only figure it out ;-)

Thanks for your feedback, I truly appreciate it.

Tim

Reply via email to