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
|
/* dl_vmesa.xs
*
* Platform: VM/ESA, possibly others which use dllload etc.
* Author: Neale Ferguson (neale@mailbox.tabnsw.com.au)
* Created: 23rd Septemer, 1998
*
*
*/
/* Porting notes:
Definition of VM/ESA dynamic Linking functions
==============================================
In order to make this implementation easier to understand here is a
quick definition of the VM/ESA Dynamic Linking functions which are
used here.
dlopen
------
void *
dlopen(const char *path)
This function takes the name of a dynamic object file and returns
a descriptor which can be used by dlsym later. It returns NULL on
error.
dllsym
------
void *
dlsym(void *handle, char *symbol)
Takes the handle returned from dlopen and the name of a symbol to
get the address of. If the symbol was found a pointer is
returned. It returns NULL on error.
dlerror
-------
char * dlerror()
Returns a null-terminated string which describes the last error
that occurred with the other dll functions. After each call to
dlerror the error message will be reset to a null pointer. The
SaveError function is used to save the error as soo as it happens.
Return Types
============
In this implementation the two functions, dl_load_file &
dl_find_symbol, return void *. This is because the underlying SunOS
dynamic linker calls also return void *. This is not necessarily
the case for all architectures. For example, some implementation
will want to return a char * for dl_load_file.
If void * is not appropriate for your architecture, you will have to
change the void * to whatever you require. If you are not certain of
how Perl handles C data types, I suggest you start by consulting
Dean Roerich's Perl 5 API document. Also, have a look in the typemap
file (in the ext directory) for a fairly comprehensive list of types
that are already supported. If you are completely stuck, I suggest you
post a message to perl5-porters, comp.lang.perl.misc or if you are really
desperate to me.
Remember when you are making any changes that the return value from
dl_load_file is used as a parameter in the dl_find_symbol
function. Also the return value from find_symbol is used as a parameter
to install_xsub.
Dealing with Error Messages
============================
In order to make the handling of dynamic linking errors as generic as
possible you should store any error messages associated with your
implementation with the StoreError function.
In the case of VM/ESA the function dlerror returns the error message
associated with the last dynamic link error. As the VM/ESA dynamic
linker functions return NULL on error every call to a VM/ESA dynamic
dynamic link routine is coded like this
RETVAL = dlopen(filename) ;
if (RETVAL == NULL)
SaveError(aTHX_ "%s",dlerror()) ;
Note that SaveError() takes a printf format string. Use a "%s" as
the first parameter if the error may contain and % characters.
*/
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <dll.h>
#include "dlutils.c" /* SaveError() etc */
static void
dl_private_init(pTHX)
{
(void)dl_generic_private_init(aTHX);
}
MODULE = DynaLoader PACKAGE = DynaLoader
BOOT:
(void)dl_private_init(aTHX);
void *
dl_load_file(filename, flags=0)
char * filename
int flags
CODE:
if (flags & 0x01)
Perl_warn(aTHX_ "Can't make loaded symbols global on this platform while loading %s",filename);
DLDEBUG(1,PerlIO_printf(PerlIO_stderr(), "dl_load_file(%s,%x):\n", filename,flags));
RETVAL = dlopen(filename) ;
DLDEBUG(2,PerlIO_printf(PerlIO_stderr(), " libref=%lx\n", (unsigned long) RETVAL));
ST(0) = sv_newmortal() ;
if (RETVAL == NULL)
SaveError(aTHX_ "%s",dlerror()) ;
else
sv_setiv( ST(0), (IV)RETVAL);
void *
dl_find_symbol(libhandle, symbolname)
void * libhandle
char * symbolname
CODE:
DLDEBUG(2, PerlIO_printf(PerlIO_stderr(),
"dl_find_symbol(handle=%lx, symbol=%s)\n",
(unsigned long) libhandle, symbolname));
RETVAL = dlsym(libhandle, symbolname);
DLDEBUG(2, PerlIO_printf(PerlIO_stderr(),
" symbolref = %lx\n", (unsigned long) RETVAL));
ST(0) = sv_newmortal() ;
if (RETVAL == NULL)
SaveError(aTHX_ "%s",dlerror()) ;
else
sv_setiv( ST(0), (IV)RETVAL);
void
dl_undef_symbols()
PPCODE:
# These functions should not need changing on any platform:
void
dl_install_xsub(perl_name, symref, filename="$Package")
char * perl_name
void * symref
char * filename
CODE:
DLDEBUG(2,PerlIO_printf(PerlIO_stderr(), "dl_install_xsub(name=%s, symref=%lx)\n",
perl_name, (unsigned long) symref));
ST(0) = sv_2mortal(newRV((SV*)newXS(perl_name,
(void(*)(pTHX_ CV *))symref,
filename)));
char *
dl_error()
CODE:
RETVAL = LastError ;
OUTPUT:
RETVAL
# end.
|