Today I belatedly discovered the usefulness of Devel::Peek.
While hacking on the newly-rebaptised Vernier::GoIO I found that get_device_info was handing me back garbage. Using Devel::Peek helped me pinpoint the problem more quickly.
get_device_info should return an array consisting of device name, vendor ID and product ID; the former is a string in hex and the latter integers required by HID USB.
Devel::Peek to the rescue. At the top of Vernier/GoIO.pm:
use Devel::Peek qw(Dump);
and in the offending routine, a strategically-placed call to Dump:
sub get_device_info {
my $handle = shift;
my @info = Sensor_GetOpenDeviceName($handle);
Dump(\@info);
die "No device info found for $handle!" unless @info;
return (
'name' => $info[0],
'vendor_id' => $info[1],
'product_id' => $info[2],
);
}
Running a test nets me this output:
SV = RV(0x82603c) at 0x86590c
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x8633bc
SV = PVAV(0x864684) at 0x8633bc
REFCNT = 2
FLAGS = (PADBUSY,PADMY)
IV = 0
NV = 0
ARRAY = 0x30b9e0
FILL = 2
MAX = 3
ARYLEN = 0x0
FLAGS = (REAL)
Elt No. 0
SV = PV(0x849ad4) at 0x866074
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x304eb0 "0x1d100000"
CUR = 10
LEN = 12
Elt No. 1
SV = IV(0x80d3ac) at 0x865954
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 8388740
Elt No. 2
SV = IV(0x80d380) at 0x8660c8
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 8388740
An array ref with three elements. Looks good. But those last two values? Not what I had in mind. I should get 2295 and 2, respectively.
perlguts gave me a clue:
Despite their suggestions in earlier versions of this document the macros (X)PUSH[iunp] are not suited to XSUBs which return multiple results. For that, either stick to the (X)PUSHs macros shown above, or use the new m(X)PUSH[iunp] macros instead; see “Putting a C value on Perl stack”.
I’d pushed three scalars on the stack, the first using the macro XPUSHs and the next two with XPUSHi:
XPUSHs(sv_2mortal(newSVpv(name, strlen(name))));
XPUSHi(sv_2mortal(newSViv(vendorId)));
XPUSHi(sv_2mortal(newSViv(productId)));
I changed the XPUSHi to XPUSHs as advised by perlguts, re(generated|compiled|tested) and lo! correct return values.
SV = RV(0x82603c) at 0x86590c
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x8633bc
SV = PVAV(0x864684) at 0x8633bc
REFCNT = 2
FLAGS = (PADBUSY,PADMY)
IV = 0
NV = 0
ARRAY = 0x30b9e0
FILL = 2
MAX = 3
ARYLEN = 0x0
FLAGS = (REAL)
Elt No. 0
SV = PV(0x849ad4) at 0x866074
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x304eb0 "0x1d100000"
CUR = 10
LEN = 12
Elt No. 1
SV = IV(0x80d334) at 0x865954
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 2295
Elt No. 2
SV = IV(0x80d3ac) at 0x8660c8
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 2
perlguts has this to say about why those two integer values were identical:
The following code will not do what you think:
XPUSHi(10);
XPUSHi(20);
This translates as “set TARG to 10, push a pointer to TARG onto the stack; set TARG to 20, push a pointer to TARG onto the stack”. At the end of the operation, the stack does not contain the values 10 and 20, but actually contains two pointers to TARG, which we have set to 20.
Okay then. Point taken, and mental note made to study
“Putting a C Value on the Perl Stack” more closely.