Discussion:
blessed hash reference
(too old to reply)
Jeffrey Ratcliffe
2008-09-15 07:11:26 UTC
Permalink
Having got the C-Perl interface working (1:1 C:XS mapping) and seen
what I already new, that it wasn't very OO or Perlish, I wrote a
pure-Perl interface, which calls, of course, the XS.

All that works nicely, but I see I have many Perl subs which exist
solely to take a blessed hash reference and return the type that the
XS and C expects. i.e. a bit of complexity in the XS would eliminate
90% of the .pm.

I now have some code working with the hash reference, but the blessed
bit of the typemap is eluding me.

As an example, below is a DESTROY routine:

MODULE = SANE PACKAGE = SANE::Device PREFIX = sane_

PROTOTYPES: ENABLE

void
sane_DESTROY (dev)
SV * dev
INIT:
HV * hv;
SV ** shandle;
SANE_Handle phandle;
CODE:
hv = (HV *) SvRV (dev);
shandle = hv_fetch (hv, "_h", 2, 0);
if (shandle == NULL || ! SvIOK(*shandle))
croak("Invalid SANE_Handle");
phandle = INT2PTR(SANE_Handle, SvIV(*shandle));
sane_close(phandle);

It seems to me that I should be able to have

SANE::Device dev

instead of

SV * dev

and add

SANE::Device T_PTROBJ

to the typemap, but I get

SANE.c:485: error: `SANE__Device' undeclared (first use in this function)

What am I missing?

Jeff
Muppet
2008-09-15 12:28:06 UTC
Permalink
Post by Jeffrey Ratcliffe
void
sane_DESTROY (dev)
SV * dev
HV * hv;
SV ** shandle;
SANE_Handle phandle;
...
Post by Jeffrey Ratcliffe
It seems to me that I should be able to have
SANE::Device dev
instead of
SV * dev
and add
SANE::Device T_PTROBJ
to the typemap, but I get
SANE.c:485: error: `SANE__Device' undeclared (first use in this function)
What am I missing?
Probably something like

typedef SANE_Handle SANE__Device;

The T_PTROBJ typemap assumes that you have a C type whose name is
created by converting the package name to a c type name with tr/:/_/.

You can either create a typedef as glue, or write your own typemap
which casts to the right thing. Since these names are so similar
(SANE_ versus SANE__), and SANE_Handle appears to be a pointer typedef
rather than a structure typedef i'd suggest making the typemap do the
right thing for sanity.

Here's an example, adapted from some working code i had lying around.


TYPEMAP

SANE_Handle T_SANE_HANDLE

INPUT

T_SANE_HANDLE
if (sv_derived_from($arg, \"SANE::Device\")) {
$var = INT2PTR (SANE_Handle, SvIV ((SV*)SvRV ($arg)));
} else {
croak(\"$var is not of type SANE::Device\");
}


OUTPUT

T_SANE_HANDLE
sv_setref_pv($arg, \"SANE_Handle\", (void*)$var);



--
So this new album took us quite a while, to get it together, to find a
title and things like that - and we were travelling quite a bit - we
made a few sort of gestures in the East, and a few gestures in the
West, and then we got thrown out because of our gestures - this is
something that we decided was an apt title for a thing that's called
'The Song Remains The Same'.
-- Robert Plant, rambling to introduce a song
Jeffrey Ratcliffe
2008-09-16 07:01:30 UTC
Permalink
Post by Muppet
Here's an example, adapted from some working code i had lying around.
Excellent. Thank you. This also forced me to simplify the code by
blessing a scalar ref, rather than a hash ref.

Jeff

Loading...