comparison python/pydc/pydcext.c @ 0:0cfcc391201f

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:26:28 +0100
parents
children bf5625bb6f05
comparison
equal deleted inserted replaced
-1:000000000000 0:0cfcc391201f
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