This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate:
[perl5.git] / os2 / OS2 / REXX / DLL / DLL.pm
CommitLineData
ed344e4f
IZ
1package OS2::DLL;
2
28b605d8
JH
3our $VERSION = '1.00';
4
ed344e4f 5use Carp;
8257dec7 6use XSLoader;
ed344e4f 7
ed344e4f
IZ
8@libs = split(/;/, $ENV{'PERL5REXX'} || $ENV{'PERLREXX'} || $ENV{'LIBPATH'} || $ENV{'PATH'});
9%dlls = ();
10
11# Preloaded methods go here. Autoload methods go after __END__, and are
12# processed by the autosplit program.
13
18729d3e 14# Cannot be autoload, the autoloader is used for the REXX functions.
ed344e4f 15
18729d3e
JH
16my $load_with_dirs = sub {
17 my ($class, $file, @where) = (@_);
ed344e4f
IZ
18 return $dlls{$file} if $dlls{$file};
19 my $handle;
20 foreach (@where) {
21 $handle = DynaLoader::dl_load_file("$_/$file.dll");
22 last if $handle;
23 }
24 $handle = DynaLoader::dl_load_file($file) unless $handle;
25 return undef unless $handle;
18729d3e
JH
26 my @packs = $INC{'OS2/REXX.pm'} ? qw(OS2::DLL::dll OS2::REXX) : 'OS2::DLL::dll';
27 my $p = "OS2::DLL::dll::$file";
28 @{"$p\::ISA"} = @packs;
29 *{"$p\::AUTOLOAD"} = \&OS2::DLL::dll::AUTOLOAD;
ed344e4f 30 return $dlls{$file} =
18729d3e
JH
31 bless {Handle => $handle, File => $file, Queue => 'SESSION' }, $p;
32};
33
34my $new_dll = sub {
35 my ($dirs, $class, $file) = (shift, shift, shift);
36 my $handle;
37 push @_, @libs if $dirs;
38 $handle = $load_with_dirs->($class, $file, @_)
39 and return $handle;
40 my $path = @_ ? " from '@_'" : '';
41 my $err = DynaLoader::dl_error();
42 $err =~ s/\s+at\s+\S+\s+line\s+\S+\s*\z//;
43 croak "Can't load '$file'$path: $err";
44};
45
46sub new {
47 confess 'Usage: OS2::DLL->new( <file> [<dirs>] )' unless @_ >= 2;
48 $new_dll->(1, @_);
ed344e4f
IZ
49}
50
18729d3e
JH
51sub module {
52 confess 'Usage: OS2::DLL->module( <file> [<dirs>] )' unless @_ >= 2;
53 $new_dll->(0, @_);
54}
55
56sub load {
57 confess 'Usage: load OS2::DLL <file> [<dirs>]' unless $#_ >= 1;
58 $load_with_dirs->(@_, @libs);
59}
60
61package OS2::DLL::dll;
62use Carp;
63@ISA = 'OS2::DLL';
64
65sub AUTOLOAD {
66 $AUTOLOAD =~ /^OS2::DLL::dll::.+::(.+)$/
67 or confess("Undefined subroutine &$AUTOLOAD called");
68 return undef if $1 eq "DESTROY";
69 die "AUTOLOAD loop" if $1 eq "AUTOLOAD";
70 $_[0]->find($1) or confess($@);
71 goto &$AUTOLOAD;
72}
73
74sub wrapper_REXX {
75 confess 'Usage: $dllhandle->wrapper_REXX($func_name)' unless @_ == 2;
ed344e4f
IZ
76 my $self = shift;
77 my $file = $self->{File};
78 my $handle = $self->{Handle};
79 my $prefix = exists($self->{Prefix}) ? $self->{Prefix} : "";
80 my $queue = $self->{Queue};
18729d3e
JH
81 my $name = shift;
82 $prefix = '' if $name =~ /^#\d+/; # loading by ordinal
83 my $addr = (DynaLoader::dl_find_symbol($handle, uc $prefix.$name)
84 || DynaLoader::dl_find_symbol($handle, $prefix.$name));
85 return sub {
86 OS2::DLL::_call($name, $addr, $queue, @_);
87 } if $addr;
88 my $err = DynaLoader::dl_error();
89 $err =~ s/\s+at\s+\S+\s+line\s+\S+\s*\z//;
90 croak "Can't find symbol `$name' in DLL `$file': $err";
ed344e4f 91}
18729d3e
JH
92
93sub find
94{
95 my $self = shift;
96 my $file = $self->{File};
97 my $p = ref $self;
98 foreach (@_) {
99 my $f = eval {$self->wrapper_REXX($_)} or return 0;
100 ${"${p}::"}{$_} = sub { shift; $f->(@_) };
ed344e4f
IZ
101 }
102 return 1;
103}
104
8257dec7 105XSLoader::load 'OS2::DLL';
ed344e4f
IZ
106
1071;
108__END__
109
110=head1 NAME
111
112OS2::DLL - access to DLLs with REXX calling convention.
113
114=head2 NOTE
115
116When you use this module, the REXX variable pool is not available.
117
118See documentation of L<OS2::REXX> module if you need the variable pool.
119
120=head1 SYNOPSIS
121
122 use OS2::DLL;
18729d3e 123 $emx_dll = OS2::DLL->module('emx');
ed344e4f 124 $emx_version = $emx_dll->emx_revision();
18729d3e
JH
125 $func_emx_version = $emx_dll->wrapper_REXX('#128'); # emx_revision
126 $emx_version = $func_emx_version->();
ed344e4f
IZ
127
128=head1 DESCRIPTION
129
18729d3e 130=head2 Create a DLL handle
ed344e4f 131
18729d3e 132 $dll = OS2::DLL->module( NAME [, WHERE] );
ed344e4f 133
18729d3e
JH
134Loads an OS/2 module NAME, looking in directories WHERE (adding the
135extension F<.dll>), if the DLL is not found there, loads in the usual OS/2 way
136(via LIBPATH and other settings). Croaks with a verbose report on failure.
ed344e4f 137
18729d3e 138The DLL is not unloaded when the return value is destroyed.
ed344e4f 139
18729d3e 140=head2 Create a DLL handle (looking in some strange locations)
ed344e4f 141
18729d3e 142 $dll = OS2::DLL->new( NAME [, WHERE] );
a748068b 143
18729d3e
JH
144Same as L<C<module>|Create a DLL handle>, but in addition to WHERE, looks
145in environment paths PERL5REXX, PERLREXX, PATH (provided for backward
146compatibility).
a748068b 147
18729d3e 148=head2 Loads DLL by name
a748068b 149
18729d3e
JH
150 $dll = load OS2::DLL NAME [, WHERE];
151
152Same as L<C<new>|Create a DLL handle (looking in some strange locations)>,
153but returns DLL object reference, or undef on failure (in this case one can
154get the reason via C<DynaLoader::dl_error()>) (provided for backward
155compatibility).
ed344e4f
IZ
156
157=head2 Check for functions (optional):
158
159 BOOL = $dll->find(NAME [, NAME [, ...]]);
160
18729d3e
JH
161Returns true if all functions are available. As a side effect, creates
162a REXX wrapper with the specified name in the package constructed by the name
163of the DLL so that the next call to C<$dll->NAME()> will pick up the cached
164method.
165
166=head2 Create a Perl wrapper (optional):
167
168 $func = $dll->wrapper_REXX(NAME);
169
170Returns a reference to a Perl function wrapper for the entry point NAME
171in the DLL. Similar to the OS/2 API, the NAME may be C<"#123"> - in this case
172the ordinal is loaded. Croaks with a meaningful error message if NAME does
173not exists (although the message for the case when the name is an ordinal may
174be confusing).
175
176=head2 Call external function with REXX calling convention:
177
178 $ret_string = $dll->function_name(arguments);
179
180Returns the return string if the REXX return code is 0, else undef.
181Dies with error message if the function is not available. On the first call
182resolves the name in the DLL and caches the Perl wrapper; future calls go
183through the wrapper.
184
185Unless used inside REXX environment (see L<OS2::REXX>), the REXX runtime
186environment (variable pool, queue etc.) is not available to the called
187function.
188
189=head1 Low-level API
190
191=over
192
193=item Call a _System linkage function via a pointer
194
195If a function takes up to 20 ULONGs and returns ULONG:
196
197 $res = call20( $pointer, $arg0, $arg1, ...);
198
199=item Same for packed arguments:
200
201 $res = call20_p( $pointer, pack 'L20', $arg0, $arg1, ...);
202
203=item Same for C<regparm(3)> function:
204
205 $res = call20_rp3( $pointer, $arg0, $arg1, ...);
206
207=item Same for packed arguments and C<regparm(3)> function
208
209 $res = call20_rp3_p( $pointer, pack 'L20', $arg0, $arg1, ...);
210
211=item Same for a function which returns non-0 and sets system-error on error
212
213 call20_Dos( $msg, $pointer, $arg0, $arg1, ...); # die("$msg: $^E") if error
214
215[Good for C<Dos*> API - and rare C<Win*> calls.]
216
217=item Same for a function which returns 0 and sets WinLastError() on error
218
219 $res = call20_Win( $msg, $pointer, $arg0, $arg1, ...);
220 # would die("$msg: $^E") if error
221
222[Good for most of C<Win*> API.]
223
224=item Same for a function which returns 0 and sets WinLastError() on error but
2250 is also a valid return
226
227 $res = call20_Win_0OK( $msg, $pointer, $arg0, $arg1, ...);
228 # would die("$msg: $^E") if error
229
230[Good for some of C<Win*> API.]
231
232=item As previous, but without die()
ed344e4f 233
18729d3e
JH
234 $res = call20_Win_0OK_survive( $pointer, $arg0, $arg1, ...);
235 if ($res == 0 and $^E) { # Do error processing here
236 }
ed344e4f 237
18729d3e 238[Good for some of C<Win*> API.]
ed344e4f 239
18729d3e 240=back
ed344e4f
IZ
241
242=head1 ENVIRONMENT
243
244If C<PERL_REXX_DEBUG> is set, emits debugging output. Looks for DLLs
245in C<PERL5REXX>, C<PERLREXX>, C<PATH>.
246
247=head1 AUTHOR
248
18729d3e 249Extracted by Ilya Zakharevich perl-module-OS2-DLL@ilyaz.org from L<OS2::REXX>
ed344e4f
IZ
250written by Andreas Kaiser ak@ananke.s.bawue.de.
251
252=cut