0
|
1 /******************************************************************************
|
|
2 **
|
|
3 ** pydc - python dyncall package
|
|
4 **
|
|
5 ** python extension package in C
|
|
6 ** Copyright 2007 Daniel Adler.
|
|
7 **
|
|
8 ** December 04, 2007
|
|
9 **
|
|
10 *****************************************************************************/
|
|
11
|
|
12 #include <Python.h>
|
|
13 #include "dynload.h"
|
|
14 #include <limits.h>
|
|
15
|
|
16 /* PyCObject destructor callback for libhandle */
|
|
17
|
|
18 void free_library(void* libhandle)
|
|
19 {
|
|
20 if (libhandle != 0)
|
|
21 dlFreeLibrary(libhandle);
|
|
22 }
|
|
23
|
|
24 /* load function */
|
|
25
|
|
26 static PyObject*
|
|
27 pydc_load(PyObject* self, PyObject* args)
|
|
28 {
|
|
29 const char* libpath;
|
|
30 void* libhandle;
|
|
31
|
|
32 if ( !PyArg_ParseTuple(args,"s", &libpath) ) return PyErr_Format(PyExc_RuntimeError, "libpath argument (string) missing");
|
|
33
|
|
34 libhandle = dlLoadLibrary(libpath);
|
|
35
|
|
36 if (!libhandle) return PyErr_Format(PyExc_RuntimeError, "dlLoadLibrary('%s') failed", libpath);
|
|
37
|
|
38 return PyCObject_FromVoidPtr(libhandle, &free_library);
|
|
39 }
|
|
40
|
|
41 /* find function */
|
|
42
|
|
43 static PyObject*
|
|
44 pydc_find(PyObject* self, PyObject* args)
|
|
45 {
|
|
46 PyObject* pcobj;
|
|
47 const char* symbol;
|
|
48 void* libhandle;
|
|
49 void* funcptr;
|
|
50
|
|
51 if ( !PyArg_ParseTuple(args,"Os", &pcobj, &symbol) ) return PyErr_Format(PyExc_RuntimeError, "argument mismatch");
|
|
52
|
|
53 libhandle = PyCObject_AsVoidPtr(pcobj);
|
|
54
|
|
55 if (!libhandle) return PyErr_Format(PyExc_RuntimeError, "libhandle is null");
|
|
56
|
|
57 funcptr = dlFindSymbol(libhandle, symbol);
|
|
58 if (!funcptr)
|
|
59 return PyErr_Format(PyExc_RuntimeError, "symbol '%s' not found", symbol);
|
|
60
|
|
61 return PyCObject_FromVoidPtr(funcptr, NULL);
|
|
62 }
|
|
63
|
|
64 /* free function */
|
|
65
|
|
66 static PyObject*
|
|
67 pydc_free(PyObject* self, PyObject* args)
|
|
68 {
|
|
69 PyObject* pcobj;
|
|
70 void* libhandle;
|
|
71
|
|
72 if ( !PyArg_ParseTuple(args,"o", &pcobj) ) return PyErr_Format(PyExc_RuntimeError, "argument mismatch");
|
|
73
|
|
74 libhandle = PyCObject_AsVoidPtr(pcobj);
|
|
75
|
|
76 if (!libhandle) return PyErr_Format(PyExc_RuntimeError, "libhandle is NULL");
|
|
77
|
|
78 dlFreeLibrary(libhandle);
|
|
79 PyCObject_SetVoidPtr(pcobj,0);
|
|
80 Py_RETURN_NONE;
|
|
81 }
|
|
82
|
|
83 #include "dyncall.h"
|
|
84 #include "dyncall_signature.h"
|
|
85
|
|
86 DCCallVM* gpCall;
|
|
87
|
|
88 /* call function */
|
|
89
|
|
90 static PyObject*
|
|
91 pydc_call(PyObject* self, PyObject* in_args)
|
|
92 {
|
|
93 PyObject* pcobj_funcptr;
|
|
94 const char* signature;
|
|
95 PyObject* args;
|
|
96 int l;
|
|
97 const char* ptr;
|
|
98 char ch;
|
|
99 int pos;
|
|
100 void* pfunc;
|
|
101
|
|
102 if ( !PyArg_ParseTuple(in_args,"OsO", &pcobj_funcptr, &signature, &args) ) return PyErr_Format(PyExc_RuntimeError, "argument mismatch");
|
|
103 pfunc = PyCObject_AsVoidPtr(pcobj_funcptr);
|
|
104 if ( !pfunc ) return PyErr_Format( PyExc_RuntimeError, "function pointer is NULL" );
|
|
105 l = PyTuple_Size(args);
|
|
106
|
|
107 ptr = signature;
|
|
108 pos = 0;
|
|
109
|
|
110 dcReset(gpCall);
|
|
111
|
|
112 while ( (ch = *ptr) != '\0' && ch != ')' )
|
|
113 {
|
|
114 PyObject* po;
|
|
115
|
|
116 int index = pos+1;
|
|
117
|
|
118 if (pos > l) return PyErr_Format( PyExc_RuntimeError, "expecting more arguments" );
|
|
119
|
|
120 po = PyTuple_GetItem(args,pos);
|
|
121
|
|
122 switch(ch)
|
|
123 {
|
|
124 case DC_SIGCHAR_BOOL:
|
|
125 {
|
|
126 DCbool b;
|
|
127 if ( !PyBool_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a bool", index );
|
|
128 b = (Py_True == po) ? DC_TRUE : DC_FALSE;
|
|
129 dcArgBool(gpCall, b);
|
|
130 }
|
|
131 break;
|
|
132 case DC_SIGCHAR_CHAR:
|
|
133 {
|
|
134 DCchar c;
|
|
135 if ( PyString_Check(po) )
|
|
136 {
|
|
137 // Py_ssize_t l;
|
|
138 size_t l;
|
|
139 char* s;
|
|
140 l = PyString_GET_SIZE(po);
|
|
141 if (l != 1) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a string with length of 1 (a char string)", index );
|
|
142 s = PyString_AsString(po);
|
|
143 c = (DCchar) s[0];
|
|
144 }
|
|
145 else if ( PyInt_Check(po) )
|
|
146 {
|
|
147 long l;
|
|
148 l = PyInt_AsLong(po);
|
|
149 if ( (l > CHAR_MAX) || (l < CHAR_MIN)) return PyErr_Format( PyExc_RuntimeError, "value out of range at argument %d - expecting a char code", index );
|
|
150 c = (DCchar) l;
|
|
151 }
|
|
152 else return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a char", index );
|
|
153 dcArgChar(gpCall, c);
|
|
154 }
|
|
155 break;
|
|
156 case DC_SIGCHAR_SHORT:
|
|
157 {
|
|
158 DCshort s;
|
|
159 long v;
|
|
160 if ( !PyInt_Check(po) )
|
|
161 return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a short int", index );
|
|
162 v = PyInt_AS_LONG(po);
|
|
163 if ( (v < SHRT_MIN) || (v > SHRT_MAX) )
|
|
164 return PyErr_Format( PyExc_RuntimeError, "value out of range at argument %d - expecting a short value", index );
|
|
165 s = (DCshort) v;
|
|
166 dcArgShort(gpCall, s);
|
|
167 }
|
|
168 break;
|
|
169 case DC_SIGCHAR_INT:
|
|
170 {
|
|
171 long v;
|
|
172 if ( !PyInt_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting an int", index );
|
|
173 v = PyInt_AS_LONG(po);
|
|
174 dcArgInt(gpCall, (DCint) v );
|
|
175 }
|
|
176 break;
|
|
177 case DC_SIGCHAR_LONG:
|
|
178 {
|
|
179 long v;
|
|
180 if ( !PyInt_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting an int", index );
|
|
181 v = PyInt_AsLong(po);
|
|
182
|
|
183 }
|
|
184 break;
|
|
185 case DC_SIGCHAR_LONGLONG:
|
|
186 {
|
|
187 PY_LONG_LONG pl;
|
|
188 DClonglong dl;
|
|
189 if ( !PyLong_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a long long", index );
|
|
190 pl = PyLong_AsLongLong(po);
|
|
191 dl = (DClonglong) pl;
|
|
192 dcArgLongLong(gpCall, dl );
|
|
193 }
|
|
194 break;
|
|
195 case DC_SIGCHAR_FLOAT:
|
|
196 {
|
|
197 DCfloat f;
|
|
198 if (!PyFloat_Check(po)) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expeecting a float", index );
|
|
199 f = (float) PyFloat_AsDouble(po);
|
|
200 dcArgFloat(gpCall, f);
|
|
201 }
|
|
202 break;
|
|
203 case DC_SIGCHAR_DOUBLE:
|
|
204 {
|
|
205 double d;
|
|
206 if (!PyFloat_Check(po)) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expeecting a float", index );
|
|
207 d = PyFloat_AsDouble(po);
|
|
208 dcArgDouble(gpCall, d);
|
|
209 }
|
|
210 break;
|
|
211 case DC_SIGCHAR_POINTER:
|
|
212 {
|
|
213 DCpointer ptr;
|
|
214 if ( PyString_Check(po) ) {
|
|
215 ptr = (DCpointer) PyString_AsString(po);
|
|
216 } else if ( PyLong_Check(po) ) {
|
|
217 ptr = (DCpointer) ( (DCint) PyLong_AsLongLong(po) );
|
|
218 } else {
|
|
219 return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a promoting pointer-type (int,string)", index );
|
|
220 }
|
|
221 dcArgPointer(gpCall, ptr );
|
|
222 }
|
|
223 break;
|
|
224 case 'S':
|
|
225 {
|
|
226 char* p;
|
|
227 if (!PyString_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a string", index );
|
|
228 p = PyString_AsString(po);
|
|
229 dcArgPointer(gpCall, (DCpointer) p );
|
|
230 }
|
|
231 break;
|
|
232 default: return PyErr_Format( PyExc_RuntimeError, "unknown signature character '%c'", ch);
|
|
233 }
|
|
234
|
|
235 ++pos; ++ptr;
|
|
236
|
|
237 }
|
|
238
|
|
239 if (pos != l) return PyErr_Format( PyExc_RuntimeError, "too many arguments");
|
|
240
|
|
241 if (ch == '\0') return PyErr_Format( PyExc_RuntimeError, "return value missing in signature");
|
|
242
|
|
243 ch = *++ptr;
|
|
244
|
|
245 switch(ch)
|
|
246 {
|
|
247 case DC_SIGCHAR_VOID: dcCallVoid(gpCall, pfunc); Py_RETURN_NONE;
|
|
248 case DC_SIGCHAR_BOOL: return Py_BuildValue("i", dcCallBool(gpCall, pfunc) );
|
|
249 case DC_SIGCHAR_INT: return Py_BuildValue("i", dcCallInt(gpCall, pfunc) );
|
|
250 case DC_SIGCHAR_LONGLONG: return Py_BuildValue("L", (unsigned long long) dcCallLongLong(gpCall, pfunc) );
|
|
251 case DC_SIGCHAR_FLOAT: return Py_BuildValue("f", dcCallFloat(gpCall, pfunc) );
|
|
252 case DC_SIGCHAR_DOUBLE: return Py_BuildValue("d", dcCallDouble(gpCall, pfunc) );
|
|
253 case 's': return Py_BuildValue("s", dcCallPointer(gpCall, pfunc) );
|
|
254 case DC_SIGCHAR_POINTER: return Py_BuildValue("p", dcCallPointer(gpCall, pfunc) );
|
|
255 default: return PyErr_Format( PyExc_RuntimeError, "invalid return type signature" );
|
|
256 }
|
|
257 }
|
|
258
|
|
259
|
|
260 static PyMethodDef pydcMethods[] = {
|
|
261 {"load", pydc_load, METH_VARARGS, "load library"},
|
|
262 {"find", pydc_find, METH_VARARGS, "find symbols"},
|
|
263 {"free", pydc_free, METH_VARARGS, "free library"},
|
|
264 {"call", pydc_call, METH_VARARGS, "call function"},
|
|
265 {NULL,NULL,0,NULL}
|
|
266 };
|
|
267
|
|
268 PyMODINIT_FUNC
|
|
269 initpydcext(void)
|
|
270 {
|
|
271 PyObject* m;
|
|
272 m = Py_InitModule("pydcext", pydcMethods);
|
|
273 if (m == NULL)
|
|
274 return;
|
|
275 gpCall = dcNewCallVM(4096);
|
|
276 }
|
|
277
|
|
278
|