This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
threads is no longer customized, as of commit c0ff91434b
[perl5.git] / ext / DynaLoader / dl_dllload.xs
CommitLineData
ac9901e0
PP
1/* dl_dllload.xs
2 *
3 * Platform: OS/390, possibly others that use dllload(),dllfree() (VM/ESA?).
4 * Authors: John Goodyear && Peter Prymmer
5 * Created: 28 October 2000
6 * Modified:
7 * 16 January 2001 - based loosely on dl_dlopen.xs.
8 */
9
10/* Porting notes:
11
12 OS/390 Dynamic Loading functions:
13
14 dllload
15 -------
16 dllhandle * dllload(const char *dllName)
17
18 This function takes the name of a dynamic object file and returns
19 a descriptor which can be used by dlllqueryfn() and/or dllqueryvar()
20 later. If dllName contains a slash, it is used to locate the dll.
21 If not then the LIBPATH environment variable is used to
22 search for the requested dll (at least within the HFS).
23 It returns NULL on error and sets errno.
24
25 dllfree
26 -------
27 int dllfree(dllhandle *handle);
28
29 dllfree() decrements the load count for the dll and frees
30 it if the count is 0. It returns zero on success, and
31 non-zero on failure.
32
33 dllqueryfn && dllqueryvar
34 -------------------------
35 void (* dllqueryfn(dllhandle *handle, const char *function))();
36 void * dllqueryvar(dllhandle *handle, const char *symbol);
37
38 dllqueryfn() takes the handle returned from dllload() and the name
39 of a function to get the address of. If the function was found
40 a pointer is returned, otherwise NULL is returned.
41
42 dllqueryvar() takes the handle returned from dllload() and the name
43 of a symbol to get the address of. If the variable was found a
44 pointer is returned, otherwise NULL is returned.
45
46 The XS dl_find_symbol() first calls dllqueryfn(). If it fails
47 dlqueryvar() is then called.
48
49 strerror
50 --------
51 char * strerror(int errno)
52
53 Returns a null-terminated string which describes the last error
54 that occurred with other functions (not necessarily unique to
55 dll loading).
56
57 Return Types
58 ============
59 In this implementation the two functions, dl_load_file() &&
60 dl_find_symbol(), return (void *). This is primarily because the
61 dlopen() && dlsym() style dynamic linker calls return (void *).
62 We suspect that casting to (void *) may be easier than teaching XS
63 typemaps about the (dllhandle *) type.
64
65 Dealing with Error Messages
66 ===========================
67 In order to make the handling of dynamic linking errors as generic as
68 possible you should store any error messages associated with your
69 implementation with the StoreError function.
70
71 In the case of OS/390 the function strerror(errno) returns the error
72 message associated with the last dynamic link error. As the S/390
73 dynamic linker functions dllload() && dllqueryvar() both return NULL
74 on error every call to an S/390 dynamic link routine is coded
75 like this:
76
77 RETVAL = dllload(filename) ;
78 if (RETVAL == NULL)
79 SaveError("%s",strerror(errno)) ;
80
81 Note that SaveError() takes a printf format string. Use a "%s" as
82 the first parameter if the error may contain any % characters.
83
84 Other comments within the dl_dlopen.xs file may be helpful as well.
85*/
86
87#include "EXTERN.h"
88#include "perl.h"
89#include "XSUB.h"
90
91#include <dll.h> /* the dynamic linker include file for S/390 */
92#include <errno.h> /* strerror() and friends */
93
94#include "dlutils.c" /* SaveError() etc */
95
96static void
97dl_private_init(pTHX)
98{
99 (void)dl_generic_private_init(aTHX);
100}
101
102MODULE = DynaLoader PACKAGE = DynaLoader
103
104BOOT:
105 (void)dl_private_init(aTHX);
106
107
63d7ac5f 108void
ac9901e0
PP
109dl_load_file(filename, flags=0)
110 char * filename
111 int flags
112 PREINIT:
113 int mode = 0;
63d7ac5f
S
114 void *retv;
115 PPCODE:
ac9901e0
PP
116 DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_load_file(%s,%x):\n", filename,flags));
117 /* add a (void *) dllload(filename) ; cast if needed */
63d7ac5f
S
118 retv = dllload(filename) ;
119 DLDEBUG(2,PerlIO_printf(Perl_debug_log, " libref=%lx\n", (unsigned long) retv));
ac9901e0 120 ST(0) = sv_newmortal() ;
63d7ac5f 121 if (retv == NULL)
ac9901e0
PP
122 SaveError(aTHX_ "%s",strerror(errno)) ;
123 else
63d7ac5f
S
124 sv_setiv( ST(0), PTR2IV(retv));
125 XSRETURN(1);
ac9901e0
PP
126
127
128int
129dl_unload_file(libref)
130 void * libref
131 CODE:
132 DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_unload_file(%lx):\n", PTR2ul(libref)));
133 /* RETVAL = (dllfree((dllhandle *)libref) == 0 ? 1 : 0); */
134 RETVAL = (dllfree(libref) == 0 ? 1 : 0);
135 if (!RETVAL)
136 SaveError(aTHX_ "%s", strerror(errno)) ;
137 DLDEBUG(2,PerlIO_printf(Perl_debug_log, " retval = %d\n", RETVAL));
138 OUTPUT:
139 RETVAL
140
141
63d7ac5f 142void
ac9901e0
PP
143dl_find_symbol(libhandle, symbolname)
144 void * libhandle
145 char * symbolname
63d7ac5f
S
146 PREINIT:
147 void *retv;
148 PPCODE:
ac9901e0
PP
149 DLDEBUG(2, PerlIO_printf(Perl_debug_log,
150 "dl_find_symbol(handle=%lx, symbol=%s)\n",
151 (unsigned long) libhandle, symbolname));
63d7ac5f
S
152 if((retv = (void*)dllqueryfn(libhandle, symbolname)) == NULL)
153 retv = dllqueryvar(libhandle, symbolname);
ac9901e0 154 DLDEBUG(2, PerlIO_printf(Perl_debug_log,
63d7ac5f 155 " symbolref = %lx\n", (unsigned long) retv));
ac9901e0 156 ST(0) = sv_newmortal() ;
63d7ac5f 157 if (retv == NULL)
ac9901e0
PP
158 SaveError(aTHX_ "%s",strerror(errno)) ;
159 else
63d7ac5f
S
160 sv_setiv( ST(0), PTR2IV(retv));
161 XSRETURN(1);
ac9901e0
PP
162
163
164void
165dl_undef_symbols()
63d7ac5f 166 CODE:
ac9901e0
PP
167
168
169
170# These functions should not need changing on any platform:
171
172void
173dl_install_xsub(perl_name, symref, filename="$Package")
174 char * perl_name
175 void * symref
d3f5e399 176 const char * filename
63d7ac5f 177 PPCODE:
ac9901e0
PP
178 DLDEBUG(2,PerlIO_printf(Perl_debug_log, "dl_install_xsub(name=%s, symref=%lx)\n",
179 perl_name, (unsigned long) symref));
77004dee
NC
180 ST(0) = sv_2mortal(newRV((SV*)newXS_flags(perl_name,
181 (void(*)(pTHX_ CV *))symref,
182 filename, NULL,
183 XS_DYNAMIC_FILENAME)));
63d7ac5f 184 XSRETURN(1);
ac9901e0
PP
185
186
bb6a367a 187SV *
ac9901e0
PP
188dl_error()
189 CODE:
cdc73a10 190 dMY_CXT;
bb6a367a 191 RETVAL = newSVsv(MY_CXT.x_dl_last_error);
ac9901e0
PP
192 OUTPUT:
193 RETVAL
194
8c472fc1
CB
195#if defined(USE_ITHREADS)
196
197void
198CLONE(...)
199 CODE:
200 MY_CXT_CLONE;
201
3bd46979
DM
202 PERL_UNUSED_VAR(items);
203
8c472fc1
CB
204 /* MY_CXT_CLONE just does a memcpy on the whole structure, so to avoid
205 * using Perl variables that belong to another thread, we create our
206 * own for this thread.
207 */
c2b90b61 208 MY_CXT.x_dl_last_error = newSVpvs("");
8c472fc1
CB
209
210#endif
211
ac9901e0 212# end.