summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl/lib/Win32/API/Callback.pm
blob: 46879b4041b27d5c9d16a16233f6529452237e98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# See the bottom of this file for the POD documentation.  Search for the
# string '=head'.

#######################################################################
#
# Win32::API::Callback - Perl Win32 API Import Facility
#
# Author: Aldo Calpini <dada@perl.it>
# Maintainer: Cosimo Streppone <cosimo@cpan.org>
#
#######################################################################

package Win32::API::Callback;

$VERSION = '0.68';

require Exporter;      # to export the constants to the main:: space
require DynaLoader;    # to dynuhlode the module.
@ISA = qw( Exporter DynaLoader );

sub DEBUG {
    if ($WIN32::API::DEBUG) {
        printf @_ if @_ or return 1;
    }
    else {
        return 0;
    }
}

use Win32::API;
use Win32::API::Type;
use Win32::API::Struct;

#######################################################################
# This AUTOLOAD is used to 'autoload' constants from the constant()
# XS function.  If a constant is not found then control is passed
# to the AUTOLOAD in AutoLoader.
#

sub AUTOLOAD {
    my ($constname);
    ($constname = $AUTOLOAD) =~ s/.*:://;

    #reset $! to zero to reset any current errors.
    $! = 0;
    my $val = constant($constname, @_ ? $_[0] : 0);
    if ($! != 0) {
        if ($! =~ /Invalid/) {
            $AutoLoader::AUTOLOAD = $AUTOLOAD;
            goto &AutoLoader::AUTOLOAD;
        }
        else {
            ($pack, $file, $line) = caller;
            die
                "Your vendor has not defined Win32::API::Callback macro $constname, used at $file line $line.";
        }
    }
    eval "sub $AUTOLOAD { $val }";
    goto &$AUTOLOAD;
}


#######################################################################
# dynamically load in the API extension module.
#
bootstrap Win32::API::Callback;

#######################################################################
# PUBLIC METHODS
#
sub new {
    my ($class, $proc, $in, $out) = @_;
    my %self = ();

    # printf "(PM)Callback::new: got proc='%s', in='%s', out='%s'\n", $proc, $in, $out;

    $self{in} = [];
    if (ref($in) eq 'ARRAY') {
        foreach (@$in) {
            push(@{$self{in}}, Win32::API::type_to_num($_));
        }
    }
    else {
        my @in = split '', $in;
        foreach (@in) {
            push(@{$self{in}}, Win32::API::type_to_num($_));
        }
    }
    $self{out} = Win32::API::type_to_num($out);
    $self{sub} = $proc;
    my $self = bless \%self, $class;

    DEBUG "(PM)Callback::new: calling CallbackCreate($self)...\n";
    my $hproc = CallbackCreate($self);

    DEBUG "(PM)Callback::new: hproc=$hproc\n";

    #### ...if that fails, set $! accordingly
    if (!$hproc) {
        $! = Win32::GetLastError();
        return undef;
    }

    #### ok, let's stuff the object
    $self->{code} = $hproc;
    $self->{sub}  = $proc;

    #### cast the spell
    return $self;
}

sub MakeStruct {
    my ($self, $n, $addr) = @_;
    DEBUG "(PM)Win32::API::Callback::MakeStruct: got self='$self'\n";
    my $struct = Win32::API::Struct->new($self->{intypes}->[$n]);
    $struct->FromMemory($addr);
    return $struct;
}

1;

__END__

#######################################################################
# DOCUMENTATION
#

=head1 NAME

Win32::API::Callback - Callback support for Win32::API

=head1 SYNOPSIS

  use Win32::API;
  use Win32::API::Callback;

  my $callback = Win32::API::Callback->new(
    sub { my($a, $b) = @_; return $a+$b; },
    "NN", "N",
  );

  Win32::API->Import(
      'mydll', 'two_integers_cb', 'KNN', 'N',
  );

  $sum = two_integers_cb( $callback, 3, 2 );


=head1 FOREWORDS

=over 4

=item *
Support for this module is B<highly experimental> at this point.

=item *
I won't be surprised if it doesn't work for you.

=item *
Feedback is very appreciated.

=item *
Documentation is in the work. Either see the SYNOPSIS above
or the samples in the F<samples> directory.

=back

=head1 AUTHOR

Aldo Calpini ( I<dada@perl.it> ).

=head1 MAINTAINER

Cosimo Streppone ( I<cosimo@cpan.org> ).

=cut