Mercurial > pub > dyncall > bindings
annotate python/pydc/pydcext.c @ 24:681db37a300c
- prep 1.0 release
author | Tassilo Philipp |
---|---|
date | Thu, 19 Apr 2018 18:54:47 +0200 |
parents | a40084782546 |
children | edbbd467f50a |
rev | line source |
---|---|
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 | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
18 void free_library(void* libhandle) |
0 | 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"); | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
52 |
0 | 53 libhandle = PyCObject_AsVoidPtr(pcobj); |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
54 |
0 | 55 if (!libhandle) return PyErr_Format(PyExc_RuntimeError, "libhandle is null"); |
56 | |
57 funcptr = dlFindSymbol(libhandle, symbol); | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
58 if (!funcptr) |
0 | 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"); | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
73 |
0 | 74 libhandle = PyCObject_AsVoidPtr(pcobj); |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
75 |
0 | 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; | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
101 |
0 | 102 if ( !PyArg_ParseTuple(in_args,"OsO", &pcobj_funcptr, &signature, &args) ) return PyErr_Format(PyExc_RuntimeError, "argument mismatch"); |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
103 pfunc = PyCObject_AsVoidPtr(pcobj_funcptr); |
0 | 104 if ( !pfunc ) return PyErr_Format( PyExc_RuntimeError, "function pointer is NULL" ); |
105 l = PyTuple_Size(args); | |
106 | |
107 ptr = signature; | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
108 pos = 0; |
0 | 109 |
110 dcReset(gpCall); | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
111 |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
112 while ( (ch = *ptr) != '\0' && ch != ')' ) |
0 | 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 | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
122 switch(ch) |
0 | 123 { |
124 case DC_SIGCHAR_BOOL: | |
125 { | |
126 DCbool b; | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
127 if ( !PyBool_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a bool", index ); |
0 | 128 b = (Py_True == po) ? DC_TRUE : DC_FALSE; |
129 dcArgBool(gpCall, b); | |
130 } | |
131 break; | |
132 case DC_SIGCHAR_CHAR: | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
133 case DC_SIGCHAR_UCHAR: |
0 | 134 { |
135 DCchar c; | |
136 if ( PyString_Check(po) ) | |
137 { | |
138 // Py_ssize_t l; | |
139 size_t l; | |
140 char* s; | |
141 l = PyString_GET_SIZE(po); | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
142 if (l != 1) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a string with length of 1 (a char string)", index ); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
143 s = PyString_AsString(po); |
0 | 144 c = (DCchar) s[0]; |
145 } | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
146 else if ( PyInt_Check(po) ) |
0 | 147 { |
148 long l; | |
149 l = PyInt_AsLong(po); | |
150 if ( (l > CHAR_MAX) || (l < CHAR_MIN)) return PyErr_Format( PyExc_RuntimeError, "value out of range at argument %d - expecting a char code", index ); | |
151 c = (DCchar) l; | |
152 } | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
153 else return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a char", index ); |
0 | 154 dcArgChar(gpCall, c); |
155 } | |
156 break; | |
157 case DC_SIGCHAR_SHORT: | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
158 case DC_SIGCHAR_USHORT: |
0 | 159 { |
160 DCshort s; | |
161 long v; | |
162 if ( !PyInt_Check(po) ) | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
163 return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a short int", index ); |
0 | 164 v = PyInt_AS_LONG(po); |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
165 if ( (v < SHRT_MIN) || (v > SHRT_MAX) ) |
0 | 166 return PyErr_Format( PyExc_RuntimeError, "value out of range at argument %d - expecting a short value", index ); |
167 s = (DCshort) v; | |
168 dcArgShort(gpCall, s); | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
169 } |
0 | 170 break; |
171 case DC_SIGCHAR_INT: | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
172 case DC_SIGCHAR_UINT: |
0 | 173 { |
174 long v; | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
175 if ( !PyInt_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting an int", index ); |
0 | 176 v = PyInt_AS_LONG(po); |
177 dcArgInt(gpCall, (DCint) v ); | |
178 } | |
179 break; | |
180 case DC_SIGCHAR_LONG: | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
181 case DC_SIGCHAR_ULONG: |
0 | 182 { |
183 long v; | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
184 if ( !PyInt_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting an int", index ); |
0 | 185 v = PyInt_AsLong(po); |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
186 |
0 | 187 } |
188 break; | |
189 case DC_SIGCHAR_LONGLONG: | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
190 case DC_SIGCHAR_ULONGLONG: |
0 | 191 { |
192 PY_LONG_LONG pl; | |
193 DClonglong dl; | |
194 if ( !PyLong_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a long long", index ); | |
195 pl = PyLong_AsLongLong(po); | |
196 dl = (DClonglong) pl; | |
197 dcArgLongLong(gpCall, dl ); | |
198 } | |
199 break; | |
200 case DC_SIGCHAR_FLOAT: | |
201 { | |
202 DCfloat f; | |
203 if (!PyFloat_Check(po)) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expeecting a float", index ); | |
204 f = (float) PyFloat_AsDouble(po); | |
205 dcArgFloat(gpCall, f); | |
206 } | |
207 break; | |
208 case DC_SIGCHAR_DOUBLE: | |
209 { | |
210 double d; | |
211 if (!PyFloat_Check(po)) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expeecting a float", index ); | |
212 d = PyFloat_AsDouble(po); | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
213 dcArgDouble(gpCall, d); |
0 | 214 } |
215 break; | |
216 case DC_SIGCHAR_POINTER: | |
217 { | |
218 DCpointer ptr; | |
219 if ( PyString_Check(po) ) { | |
220 ptr = (DCpointer) PyString_AsString(po); | |
221 } else if ( PyLong_Check(po) ) { | |
222 ptr = (DCpointer) ( (DCint) PyLong_AsLongLong(po) ); | |
223 } else { | |
224 return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a promoting pointer-type (int,string)", index ); | |
225 } | |
226 dcArgPointer(gpCall, ptr ); | |
227 } | |
228 break; | |
5 | 229 case DC_SIGCHAR_STRING: |
0 | 230 { |
231 char* p; | |
232 if (!PyString_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a string", index ); | |
233 p = PyString_AsString(po); | |
234 dcArgPointer(gpCall, (DCpointer) p ); | |
235 } | |
236 break; | |
237 default: return PyErr_Format( PyExc_RuntimeError, "unknown signature character '%c'", ch); | |
238 } | |
239 | |
240 ++pos; ++ptr; | |
241 | |
242 } | |
243 | |
244 if (pos != l) return PyErr_Format( PyExc_RuntimeError, "too many arguments"); | |
245 | |
246 if (ch == '\0') return PyErr_Format( PyExc_RuntimeError, "return value missing in signature"); | |
247 | |
248 ch = *++ptr; | |
249 | |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
250 switch(ch) |
0 | 251 { |
16
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
252 case DC_SIGCHAR_VOID: dcCallVoid (gpCall, pfunc); Py_RETURN_NONE; |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
253 case DC_SIGCHAR_BOOL: return Py_BuildValue("i", dcCallBool (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
254 case DC_SIGCHAR_CHAR: return Py_BuildValue("b", dcCallChar (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
255 case DC_SIGCHAR_UCHAR: return Py_BuildValue("B", dcCallChar (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
256 case DC_SIGCHAR_SHORT: return Py_BuildValue("h", dcCallShort (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
257 case DC_SIGCHAR_USHORT: return Py_BuildValue("H", dcCallShort (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
258 case DC_SIGCHAR_INT: return Py_BuildValue("i", dcCallInt (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
259 case DC_SIGCHAR_UINT: return Py_BuildValue("I", dcCallInt (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
260 case DC_SIGCHAR_LONG: return Py_BuildValue("l", dcCallLong (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
261 case DC_SIGCHAR_ULONG: return Py_BuildValue("k", dcCallLong (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
262 case DC_SIGCHAR_LONGLONG: return Py_BuildValue("L", dcCallLongLong(gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
263 case DC_SIGCHAR_ULONGLONG: return Py_BuildValue("K", dcCallLongLong(gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
264 case DC_SIGCHAR_FLOAT: return Py_BuildValue("f", dcCallFloat (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
265 case DC_SIGCHAR_DOUBLE: return Py_BuildValue("d", dcCallDouble (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
266 case DC_SIGCHAR_STRING: return Py_BuildValue("s", dcCallPointer (gpCall, pfunc)); |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
267 case DC_SIGCHAR_POINTER: return Py_BuildValue("p", dcCallPointer (gpCall, pfunc)); // @@@ probably not working, there is no "p" |
a40084782546
- added support for more return values to python binding
cslag
parents:
5
diff
changeset
|
268 default: return PyErr_Format(PyExc_RuntimeError, "invalid return type signature"); |
0 | 269 } |
270 } | |
271 | |
272 | |
273 static PyMethodDef pydcMethods[] = { | |
274 {"load", pydc_load, METH_VARARGS, "load library"}, | |
275 {"find", pydc_find, METH_VARARGS, "find symbols"}, | |
276 {"free", pydc_free, METH_VARARGS, "free library"}, | |
277 {"call", pydc_call, METH_VARARGS, "call function"}, | |
278 {NULL,NULL,0,NULL} | |
279 }; | |
280 | |
281 PyMODINIT_FUNC | |
282 initpydcext(void) | |
283 { | |
284 PyObject* m; | |
285 m = Py_InitModule("pydcext", pydcMethods); | |
286 if (m == NULL) | |
287 return; | |
288 gpCall = dcNewCallVM(4096); | |
289 } | |
290 |