Clarify portability and main program.
[python/dscho.git] / Modules / dlmodule.c
blob76d054017973391e2f6fe51bb3c0d6dabbf657a2
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* dl module */
34 #include "Python.h"
36 #include <dlfcn.h>
38 #ifndef RTLD_LAZY
39 #define RTLD_LAZY 1
40 #endif
42 typedef ANY *PyUnivPtr;
43 typedef struct {
44 PyObject_HEAD
45 PyUnivPtr *dl_handle;
46 } dlobject;
48 staticforward PyTypeObject Dltype;
50 static PyObject *Dlerror;
52 static PyObject *
53 newdlobject(handle)
54 PyUnivPtr *handle;
56 dlobject *xp;
57 xp = PyObject_NEW(dlobject, &Dltype);
58 if (xp == NULL)
59 return NULL;
60 xp->dl_handle = handle;
61 return (PyObject *)xp;
64 static void
65 dl_dealloc(xp)
66 dlobject *xp;
68 if (xp->dl_handle != NULL)
69 dlclose(xp->dl_handle);
70 PyMem_DEL(xp);
73 static PyObject *
74 dl_close(xp, args)
75 dlobject *xp;
76 PyObject *args;
78 if (!PyArg_Parse(args, ""))
79 return NULL;
80 if (xp->dl_handle != NULL) {
81 dlclose(xp->dl_handle);
82 xp->dl_handle = NULL;
84 Py_INCREF(Py_None);
85 return Py_None;
88 static PyObject *
89 dl_sym(xp, args)
90 dlobject *xp;
91 PyObject *args;
93 char *name;
94 PyUnivPtr *func;
95 if (!PyArg_Parse(args, "s", &name))
96 return NULL;
97 func = dlsym(xp->dl_handle, name);
98 if (func == NULL) {
99 Py_INCREF(Py_None);
100 return Py_None;
102 return PyInt_FromLong((long)func);
105 static PyObject *
106 dl_call(xp, args)
107 dlobject *xp;
108 PyObject *args; /* (varargs) */
110 PyObject *name;
111 long (*func)();
112 long alist[10];
113 long res;
114 int i;
115 int n = PyTuple_Size(args);
116 if (n < 1) {
117 PyErr_SetString(PyExc_TypeError, "at least a name is needed");
118 return NULL;
120 name = PyTuple_GetItem(args, 0);
121 if (!PyString_Check(name)) {
122 PyErr_SetString(PyExc_TypeError,
123 "function name must be a string");
124 return NULL;
126 func = dlsym(xp->dl_handle, PyString_AsString(name));
127 if (func == NULL) {
128 PyErr_SetString(PyExc_ValueError, dlerror());
129 return NULL;
131 if (n-1 > 10) {
132 PyErr_SetString(PyExc_TypeError,
133 "too many arguments (max 10)");
134 return NULL;
136 for (i = 1; i < n; i++) {
137 PyObject *v = PyTuple_GetItem(args, i);
138 if (PyInt_Check(v))
139 alist[i-1] = PyInt_AsLong(v);
140 else if (PyString_Check(v))
141 alist[i-1] = (long)PyString_AsString(v);
142 else if (v == Py_None)
143 alist[i-1] = (long) ((char *)NULL);
144 else {
145 PyErr_SetString(PyExc_TypeError,
146 "arguments must be int, string or None");
147 return NULL;
150 for (; i <= 10; i++)
151 alist[i-1] = 0;
152 res = (*func)(alist[0], alist[1], alist[2], alist[3], alist[4],
153 alist[5], alist[6], alist[7], alist[8], alist[9]);
154 return PyInt_FromLong(res);
157 static PyMethodDef dlobject_methods[] = {
158 {"call", (PyCFunction)dl_call, 1 /* varargs */},
159 {"sym", (PyCFunction)dl_sym},
160 {"close", (PyCFunction)dl_close},
161 {NULL, NULL} /* Sentinel */
164 static PyObject *
165 dl_getattr(xp, name)
166 dlobject *xp;
167 char *name;
169 return Py_FindMethod(dlobject_methods, (PyObject *)xp, name);
173 static PyTypeObject Dltype = {
174 PyObject_HEAD_INIT(&PyType_Type)
175 0, /*ob_size*/
176 "dl", /*tp_name*/
177 sizeof(dlobject), /*tp_basicsize*/
178 0, /*tp_itemsize*/
179 /* methods */
180 (destructor)dl_dealloc, /*tp_dealloc*/
181 0, /*tp_print*/
182 (getattrfunc)dl_getattr,/*tp_getattr*/
183 0, /*tp_setattr*/
184 0, /*tp_compare*/
185 0, /*tp_repr*/
186 0, /*tp_as_number*/
187 0, /*tp_as_sequence*/
188 0, /*tp_as_mapping*/
189 0, /*tp_hash*/
192 static PyObject *
193 dl_open(self, args)
194 PyObject *self;
195 PyObject *args;
197 char *name;
198 int mode;
199 PyUnivPtr *handle;
200 if (PyArg_Parse(args, "z", &name))
201 mode = RTLD_LAZY;
202 else {
203 PyErr_Clear();
204 if (!PyArg_Parse(args, "(zi)", &name, &mode))
205 return NULL;
206 #ifndef RTLD_NOW
207 if (mode != RTLD_LAZY) {
208 PyErr_SetString(PyExc_ValueError, "mode must be 1");
209 return NULL;
211 #endif
213 handle = dlopen(name, mode);
214 if (handle == NULL) {
215 PyErr_SetString(Dlerror, dlerror());
216 return NULL;
218 return newdlobject(handle);
221 static PyMethodDef dl_methods[] = {
222 {"open", dl_open},
223 {NULL, NULL} /* sentinel */
226 void
227 initdl()
229 PyObject *m, *d, *x;
231 if (sizeof(int) != sizeof(long) ||
232 sizeof(long) != sizeof(char *)) {
233 PyErr_SetString(PyExc_SystemError,
234 "module dl requires sizeof(int) == sizeof(long) == sizeof(char*)");
235 return;
238 /* Create the module and add the functions */
239 m = Py_InitModule("dl", dl_methods);
241 /* Add some symbolic constants to the module */
242 d = PyModule_GetDict(m);
243 Dlerror = x = PyErr_NewException("dl.error", NULL, NULL);
244 PyDict_SetItemString(d, "error", x);
245 x = PyInt_FromLong((long)RTLD_LAZY);
246 PyDict_SetItemString(d, "RTLD_LAZY", x);
247 #ifdef RTLD_NOW
248 x = PyInt_FromLong((long)RTLD_NOW);
249 PyDict_SetItemString(d, "RTLD_NOW", x);
250 #endif