dlmodule.c 5.78 KB
Newer Older
1
/***********************************************************
2 3
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.
4 5 6

                        All Rights Reserved

7 8
Permission to use, copy, modify, and distribute this software and its
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 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Centrum or CWI or Corporation for National Research Initiatives or
CNRI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.

While CWI is the initial source for this software, a modified version
is made available by the Corporation for National Research Initiatives
(CNRI) at the Internet address ftp://ftp.python.org.

STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
29 30 31 32 33

******************************************************************/

/* dl module */

Roger E. Masse's avatar
Roger E. Masse committed
34
#include "Python.h"
35 36 37 38 39 40 41

#include <dlfcn.h>

#ifndef RTLD_LAZY
#define RTLD_LAZY 1
#endif

Roger E. Masse's avatar
Roger E. Masse committed
42
typedef ANY *PyUnivPtr;
43
typedef struct {
Roger E. Masse's avatar
Roger E. Masse committed
44 45
	PyObject_HEAD
	PyUnivPtr *dl_handle;
46 47
} dlobject;

Roger E. Masse's avatar
Roger E. Masse committed
48
staticforward PyTypeObject Dltype;
49

Roger E. Masse's avatar
Roger E. Masse committed
50
static PyObject *Dlerror;
51

Roger E. Masse's avatar
Roger E. Masse committed
52
static PyObject *
53
newdlobject(handle)
Roger E. Masse's avatar
Roger E. Masse committed
54
	PyUnivPtr *handle;
55 56
{
	dlobject *xp;
Roger E. Masse's avatar
Roger E. Masse committed
57
	xp = PyObject_NEW(dlobject, &Dltype);
58 59 60
	if (xp == NULL)
		return NULL;
	xp->dl_handle = handle;
Roger E. Masse's avatar
Roger E. Masse committed
61
	return (PyObject *)xp;
62 63 64 65 66 67 68 69
}

static void
dl_dealloc(xp)
	dlobject *xp;
{
	if (xp->dl_handle != NULL)
		dlclose(xp->dl_handle);
Roger E. Masse's avatar
Roger E. Masse committed
70
	PyMem_DEL(xp);
71 72
}

Roger E. Masse's avatar
Roger E. Masse committed
73
static PyObject *
74 75
dl_close(xp, args)
	dlobject *xp;
Roger E. Masse's avatar
Roger E. Masse committed
76
	PyObject *args;
77
{
Roger E. Masse's avatar
Roger E. Masse committed
78
	if (!PyArg_Parse(args, ""))
79 80 81 82 83
		return NULL;
	if (xp->dl_handle != NULL) {
		dlclose(xp->dl_handle);
		xp->dl_handle = NULL;
	}
Roger E. Masse's avatar
Roger E. Masse committed
84 85
	Py_INCREF(Py_None);
	return Py_None;
86 87
}

Roger E. Masse's avatar
Roger E. Masse committed
88
static PyObject *
89 90
dl_sym(xp, args)
	dlobject *xp;
Roger E. Masse's avatar
Roger E. Masse committed
91
	PyObject *args;
92 93
{
	char *name;
Roger E. Masse's avatar
Roger E. Masse committed
94 95
	PyUnivPtr *func;
	if (!PyArg_Parse(args, "s", &name))
96 97 98
		return NULL;
	func = dlsym(xp->dl_handle, name);
	if (func == NULL) {
Roger E. Masse's avatar
Roger E. Masse committed
99 100
		Py_INCREF(Py_None);
		return Py_None;
101
	}
Roger E. Masse's avatar
Roger E. Masse committed
102
	return PyInt_FromLong((long)func);
103 104
}

Roger E. Masse's avatar
Roger E. Masse committed
105
static PyObject *
106 107
dl_call(xp, args)
	dlobject *xp;
Roger E. Masse's avatar
Roger E. Masse committed
108
	PyObject *args; /* (varargs) */
109
{
Roger E. Masse's avatar
Roger E. Masse committed
110
	PyObject *name;
111 112 113 114
	long (*func)();
	long alist[10];
	long res;
	int i;
Roger E. Masse's avatar
Roger E. Masse committed
115
	int n = PyTuple_Size(args);
116
	if (n < 1) {
Roger E. Masse's avatar
Roger E. Masse committed
117
		PyErr_SetString(PyExc_TypeError, "at least a name is needed");
118 119
		return NULL;
	}
Roger E. Masse's avatar
Roger E. Masse committed
120 121 122 123
	name = PyTuple_GetItem(args, 0);
	if (!PyString_Check(name)) {
		PyErr_SetString(PyExc_TypeError,
				"function name must be a string");
124 125
		return NULL;
	}
Roger E. Masse's avatar
Roger E. Masse committed
126
	func = dlsym(xp->dl_handle, PyString_AsString(name));
127
	if (func == NULL) {
Roger E. Masse's avatar
Roger E. Masse committed
128
		PyErr_SetString(PyExc_ValueError, dlerror());
129 130 131
		return NULL;
	}
	if (n-1 > 10) {
Roger E. Masse's avatar
Roger E. Masse committed
132 133
		PyErr_SetString(PyExc_TypeError,
				"too many arguments (max 10)");
134 135 136
		return NULL;
	}
	for (i = 1; i < n; i++) {
Roger E. Masse's avatar
Roger E. Masse committed
137 138 139 140 141 142
		PyObject *v = PyTuple_GetItem(args, i);
		if (PyInt_Check(v))
			alist[i-1] = PyInt_AsLong(v);
		else if (PyString_Check(v))
			alist[i-1] = (long)PyString_AsString(v);
		else if (v == Py_None)
143 144
			alist[i-1] = (long) ((char *)NULL);
		else {
Roger E. Masse's avatar
Roger E. Masse committed
145
			PyErr_SetString(PyExc_TypeError,
146 147 148 149 150 151 152 153
				   "arguments must be int, string or None");
			return NULL;
		}
	}
	for (; i <= 10; i++)
		alist[i-1] = 0;
	res = (*func)(alist[0], alist[1], alist[2], alist[3], alist[4],
		      alist[5], alist[6], alist[7], alist[8], alist[9]);
Roger E. Masse's avatar
Roger E. Masse committed
154
	return PyInt_FromLong(res);
155 156
}

Roger E. Masse's avatar
Roger E. Masse committed
157 158 159 160 161
static PyMethodDef dlobject_methods[] = {
	{"call",	(PyCFunction)dl_call,	1 /* varargs */},
	{"sym", 	(PyCFunction)dl_sym},
	{"close",	(PyCFunction)dl_close},
	{NULL,  	NULL}			 /* Sentinel */
162 163
};

Roger E. Masse's avatar
Roger E. Masse committed
164
static PyObject *
165 166 167 168
dl_getattr(xp, name)
	dlobject *xp;
	char *name;
{
Roger E. Masse's avatar
Roger E. Masse committed
169
	return Py_FindMethod(dlobject_methods, (PyObject *)xp, name);
170 171 172
}


Roger E. Masse's avatar
Roger E. Masse committed
173 174
static PyTypeObject Dltype = {
	PyObject_HEAD_INIT(&PyType_Type)
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
	0,			/*ob_size*/
	"dl",			/*tp_name*/
	sizeof(dlobject),	/*tp_basicsize*/
	0,			/*tp_itemsize*/
	/* methods */
	(destructor)dl_dealloc, /*tp_dealloc*/
	0,			/*tp_print*/
	(getattrfunc)dl_getattr,/*tp_getattr*/
	0,			/*tp_setattr*/
	0,			/*tp_compare*/
	0,			/*tp_repr*/
	0,			/*tp_as_number*/
	0,			/*tp_as_sequence*/
	0,			/*tp_as_mapping*/
	0,			/*tp_hash*/
};

Roger E. Masse's avatar
Roger E. Masse committed
192
static PyObject *
193
dl_open(self, args)
Roger E. Masse's avatar
Roger E. Masse committed
194 195
	PyObject *self;
	PyObject *args;
196 197 198
{
	char *name;
	int mode;
Roger E. Masse's avatar
Roger E. Masse committed
199 200
	PyUnivPtr *handle;
	if (PyArg_Parse(args, "z", &name))
201 202
		mode = RTLD_LAZY;
	else {
Roger E. Masse's avatar
Roger E. Masse committed
203 204
		PyErr_Clear();
		if (!PyArg_Parse(args, "(zi)", &name, &mode))
205 206 207
			return NULL;
#ifndef RTLD_NOW
		if (mode != RTLD_LAZY) {
Roger E. Masse's avatar
Roger E. Masse committed
208
			PyErr_SetString(PyExc_ValueError, "mode must be 1");
209 210 211 212 213 214
			return NULL;
		}
#endif
	}
	handle = dlopen(name, mode);
	if (handle == NULL) {
Roger E. Masse's avatar
Roger E. Masse committed
215
		PyErr_SetString(Dlerror, dlerror());
216 217 218 219 220
		return NULL;
	}
	return newdlobject(handle);
}

Roger E. Masse's avatar
Roger E. Masse committed
221
static PyMethodDef dl_methods[] = {
222 223 224 225 226 227 228
	{"open",	dl_open},
	{NULL,		NULL}		/* sentinel */
};

void
initdl()
{
Roger E. Masse's avatar
Roger E. Masse committed
229
	PyObject *m, *d, *x;
230 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 236
		return;
	}
237 238

	/* Create the module and add the functions */
Roger E. Masse's avatar
Roger E. Masse committed
239
	m = Py_InitModule("dl", dl_methods);
240 241

	/* Add some symbolic constants to the module */
Roger E. Masse's avatar
Roger E. Masse committed
242
	d = PyModule_GetDict(m);
243
	Dlerror = x = PyErr_NewException("dl.error", NULL, NULL);
Roger E. Masse's avatar
Roger E. Masse committed
244 245 246
	PyDict_SetItemString(d, "error", x);
	x = PyInt_FromLong((long)RTLD_LAZY);
	PyDict_SetItemString(d, "RTLD_LAZY", x);
247
#ifdef RTLD_NOW
Roger E. Masse's avatar
Roger E. Masse committed
248 249
	x = PyInt_FromLong((long)RTLD_NOW);
	PyDict_SetItemString(d, "RTLD_NOW", x);
250 251
#endif
}