Accessing Pervasive.SQL With Perl

Page Last Modified: 20/11/12

Home Links ODBC (DBI) Contact

Win32::API Examples 2 - parsing a table in DEMODATA

Here we step through the records in one of the tables in the DEMODATA sample database installed with Pervasive.SQL:

use strict;
use warnings;
use 5.010;

use Win32::API;

my $funchandle = new Win32::API("w3btrv7.dll", "BTRCALL", "IPPPPCc", "I");

if (defined $funchandle)
say "Win32::API funchandle set";
my $filename = 'c:\pvsw\demodata\course.mkd';

my $operation = 0; # open
my $posBlock = pack("a128");
my $dataBuffer = pack("a255");
my $dataLength = 0;
my $keyBuffer = pack("a255", $filename);
my $keyLength = length($filename) + 1;
my $keyNumber = 0;

say "Calling open function...";

my $return = _call_btrv($operation, \$posBlock, \$dataBuffer, \$dataLength, \$keyBuffer, $keyLength, $keyNumber);

if($return == 0)
my $count;

$operation = 33; # step first
$dataLength = 255;

say "Calling step first function...";

$return = _call_btrv($operation, \$posBlock, \$dataBuffer, \$dataLength, \$keyBuffer, $keyLength, $keyNumber);

while($return == 0)
$dataLength = unpack('S', $dataLength);

say "data buffer length = $dataLength";


$operation = 24; # step next
$dataBuffer = pack("a255");
#$dataLength = 255; # fixed length records, so we can keep using the returned size

say "Calling step next function...";

$return = _call_btrv($operation, \$posBlock, \$dataBuffer, \$dataLength, \$keyBuffer, $keyLength, $keyNumber);

say "$count records found";

$operation = 1; # close

say "Calling close function...";

$return = _call_btrv($operation, \$posBlock, \$dataBuffer, \$dataLength, \$keyBuffer, $keyLength, $keyNumber);
say "funchandle not set";


sub _call_btrv
my ($operation, $posBlockRef, $dataBufferRef, $dataLengthRef, $keyBufferRef, $keyLength, $keyNumber) = @_;

my $ret = $funchandle->Call($operation, $$posBlockRef, $$dataBufferRef, $$dataLengthRef, $$keyBufferRef, $keyLength, $keyNumber);

say "return = $ret";

return $ret;


In this example I've used pack to set up the position block, data buffer and key buffer variables instead of treating them as strings (as in the previous example). To me this looks tidier, ties in more with the fact that they are buffers, and matches the unpack calls I have to make on parameters passed into, and filled in by, the BTRCALL function. In this case I have to unpack the data buffer length parameter to convert it into an integer.

I also moved the Win32::API Call operation into its own function (_call_btrv) to tidy things up a bit and reduce the number of times I have to print the return value in terms of lines of code. I have passed references into this function those arguments that can be updated by the BTRCALL function. As a result_call_btrv looks to my eyes more like the underlying BTRCALL (and corresponding BTRAPI, etc. calls) when accessed in C and it is clearer which arguments can be changed by the call. Note that anything passed by reference into _call_btrv has to be dereferenced before being passed onto BTRCALL - as explained elsewhere, Win32::API expects parameters that are pointers/buffers to be passed by value/name and not by reference.

Home Links ODBC (DBI) Contact

All content on this site is copyright
Neil Hughes 2010 - 2018