comparison python/pydc/pydcext.c @ 29:6cc2b7fc7ea2

bigger pydc update: - cleanups and refactoring - python 2 fixes in var conversions (especially w/ respect to int vs long) - fix to pydc.free() which didn't work at all - fix to return python bool as actual bool - test lib covering all conversions (manual verification, though :-/)
author Tassilo Philipp
date Wed, 08 Apr 2020 22:17:43 +0200
parents edbbd467f50a
children baf087cf5971
comparison
equal deleted inserted replaced
28:edbbd467f50a 29:6cc2b7fc7ea2
28 # define DcPyCObject_SetVoidPtr(ppobj, ptr) PyCObject_SetVoidPtr((ppobj), (ptr)) 28 # define DcPyCObject_SetVoidPtr(ppobj, ptr) PyCObject_SetVoidPtr((ppobj), (ptr))
29 #else 29 #else
30 # define USE_CAPSULE_API 30 # define USE_CAPSULE_API
31 # define DcPyCObject_FromVoidPtr(ptr, dtor) PyCapsule_New((ptr), NULL, (dtor)) 31 # define DcPyCObject_FromVoidPtr(ptr, dtor) PyCapsule_New((ptr), NULL, (dtor))
32 # define DcPyCObject_AsVoidPtr(ppobj) PyCapsule_GetPointer((ppobj), NULL) 32 # define DcPyCObject_AsVoidPtr(ppobj) PyCapsule_GetPointer((ppobj), NULL)
33 # define DcPyCObject_SetVoidPtr(ppobj, ptr) PyCapsule_SetPointer((ppobj), (ptr)) // this might need to call the dtor to behave like PyCObject_SetVoidPtr? 33 # define DcPyCObject_SetVoidPtr(ppobj, ptr) //@@@ unsure what to do, cannot/shouldn't call this with a null pointer as this wants to call the dtor, so not doing anything: PyCapsule_SetPointer((ppobj), (ptr)) // this might need to call the dtor to behave like PyCObject_SetVoidPtr?
34 #endif 34 #endif
35 35
36 #if PY_MAJOR_VERSION >= 3 36 #if PY_MAJOR_VERSION >= 3
37 # define EXPECT_LONG_TYPE_STR "an int"
37 # define DcPyString_GET_SIZE PyBytes_GET_SIZE 38 # define DcPyString_GET_SIZE PyBytes_GET_SIZE
38 # define DcPyString_Check PyBytes_Check 39 # define DcPyString_Check PyBytes_Check
39 # define DcPyString_AsString PyBytes_AsString 40 # define DcPyString_AsString PyBytes_AsString
40 # define DcPyInt_Check PyLong_Check 41 # define DcPyInt_Check PyLong_Check
41 # define DcPyInt_AsLong PyLong_AsLong 42 # define DcPyInt_AsLong PyLong_AsLong
42 # define DcPyInt_AS_LONG PyLong_AS_LONG 43 # define DcPyInt_AS_LONG PyLong_AS_LONG
43 #else 44 #else
45 # define EXPECT_LONG_TYPE_STR "an int or a long"
44 # define DcPyString_GET_SIZE PyString_GET_SIZE 46 # define DcPyString_GET_SIZE PyString_GET_SIZE
45 # define DcPyString_Check PyString_Check 47 # define DcPyString_Check PyString_Check
46 # define DcPyString_AsString PyString_AsString 48 # define DcPyString_AsString PyString_AsString
47 # define DcPyInt_Check PyInt_Check 49 # define DcPyInt_Check PyInt_Check
48 # define DcPyInt_AsLong PyInt_AsLong 50 # define DcPyInt_AsLong PyInt_AsLong
52 /* PyCObject destructor callback for libhandle */ 54 /* PyCObject destructor callback for libhandle */
53 55
54 #if defined(USE_CAPSULE_API) 56 #if defined(USE_CAPSULE_API)
55 void free_library(PyObject* capsule) 57 void free_library(PyObject* capsule)
56 { 58 {
57 void* libhandle = PyCapsule_GetPointer(capsule, NULL); 59 void* libhandle = PyCapsule_GetPointer(capsule, NULL);
58 #else 60 #else
59 void free_library(void* libhandle) 61 void free_library(void* libhandle)
60 { 62 {
61 #endif 63 #endif
62 if (libhandle != 0) 64 if (libhandle != 0)
63 dlFreeLibrary(libhandle); 65 dlFreeLibrary(libhandle);
64 } 66 }
65 67
66 68
67 /* load function */ 69 /* load function */
68 70
69 static PyObject* 71 static PyObject*
70 pydc_load(PyObject* self, PyObject* args) 72 pydc_load(PyObject* self, PyObject* args)
71 { 73 {
72 const char* libpath; 74 const char* libpath;
73 void* libhandle; 75 void* libhandle;
74 76
75 if (!PyArg_ParseTuple(args,"s", &libpath)) 77 if (!PyArg_ParseTuple(args,"s", &libpath))
76 return PyErr_Format(PyExc_RuntimeError, "libpath argument (string) missing"); 78 return PyErr_Format(PyExc_RuntimeError, "libpath argument (string) missing");
77 79
78 libhandle = dlLoadLibrary(libpath); 80 libhandle = dlLoadLibrary(libpath);
79 81
80 if (!libhandle) 82 if (!libhandle)
81 return PyErr_Format(PyExc_RuntimeError, "dlLoadLibrary('%s') failed", libpath); 83 return PyErr_Format(PyExc_RuntimeError, "dlLoadLibrary('%s') failed", libpath);
82 84
83 return DcPyCObject_FromVoidPtr(libhandle, &free_library); 85 return DcPyCObject_FromVoidPtr(libhandle, &free_library);
84 } 86 }
85 87
86 /* find function */ 88 /* find function */
87 89
88 static PyObject* 90 static PyObject*
89 pydc_find(PyObject* self, PyObject* args) 91 pydc_find(PyObject* self, PyObject* args)
90 { 92 {
91 PyObject* pcobj; 93 PyObject* pcobj;
92 const char* symbol; 94 const char* symbol;
93 void* libhandle; 95 void* libhandle;
94 void* funcptr; 96 void* funcptr;
95 97
96 if (!PyArg_ParseTuple(args, "Os", &pcobj, &symbol)) 98 if (!PyArg_ParseTuple(args, "Os", &pcobj, &symbol))
97 return PyErr_Format(PyExc_RuntimeError, "argument mismatch"); 99 return PyErr_Format(PyExc_RuntimeError, "argument mismatch");
98 100
99 libhandle = DcPyCObject_AsVoidPtr(pcobj); 101 libhandle = DcPyCObject_AsVoidPtr(pcobj);
100 if (!libhandle) 102 if (!libhandle)
101 return PyErr_Format(PyExc_RuntimeError, "libhandle is null"); 103 return PyErr_Format(PyExc_RuntimeError, "libhandle is null");
102 104
103 funcptr = dlFindSymbol(libhandle, symbol); 105 funcptr = dlFindSymbol(libhandle, symbol);
104 if (!funcptr) 106 if (!funcptr)
105 return PyErr_Format(PyExc_RuntimeError, "symbol '%s' not found", symbol); 107 return PyErr_Format(PyExc_RuntimeError, "symbol '%s' not found", symbol);
106 108
107 return DcPyCObject_FromVoidPtr(funcptr, NULL); 109 return DcPyCObject_FromVoidPtr(funcptr, NULL);
108 } 110 }
109 111
110 /* free function */ 112 /* free function */
111 113
112 static PyObject* 114 static PyObject*
113 pydc_free(PyObject* self, PyObject* args) 115 pydc_free(PyObject* self, PyObject* args)
114 { 116 {
115 PyObject* pcobj; 117 PyObject* pcobj;
116 void* libhandle; 118 void* libhandle;
117 119
118 if (!PyArg_ParseTuple(args, "o", &pcobj)) 120 if (!PyArg_ParseTuple(args, "O", &pcobj))
119 return PyErr_Format(PyExc_RuntimeError, "argument mismatch"); 121 return PyErr_Format(PyExc_RuntimeError, "argument mismatch");
120 122
121 libhandle = DcPyCObject_AsVoidPtr(pcobj); 123 libhandle = DcPyCObject_AsVoidPtr(pcobj);
122 if (!libhandle) 124 if (!libhandle)
123 return PyErr_Format(PyExc_RuntimeError, "libhandle is NULL"); 125 return PyErr_Format(PyExc_RuntimeError, "libhandle is NULL");
124 126
125 dlFreeLibrary(libhandle); 127 dlFreeLibrary(libhandle);
126 DcPyCObject_SetVoidPtr(pcobj, NULL); 128 DcPyCObject_SetVoidPtr(pcobj, NULL);
127 129
128 Py_RETURN_NONE; 130 Py_RETURN_NONE;
129 } 131 }
130 132
131 133
132 #include "dyncall.h" 134 #include "dyncall.h"
133 #include "dyncall_signature.h" 135 #include "dyncall_signature.h"
134 136
135 DCCallVM* gpCall; 137 DCCallVM* gpCall;
136 138
139
137 /* call function */ 140 /* call function */
138 141
139 static PyObject* 142 static PyObject*
140 pydc_call(PyObject* self, PyObject* in_args) 143 pydc_call(PyObject* self, PyObject* in_args)
141 { 144 {
142 PyObject* pcobj_funcptr; 145 PyObject *pcobj_funcptr, *args;
143 const char* signature; 146 const char *signature, *ptr;
144 PyObject* args; 147 char ch;
145 int l; 148 int pos, ts;
146 const char* ptr; 149 void* pfunc;
147 char ch; 150
148 int pos; 151 if (!PyArg_ParseTuple(in_args,"OsO", &pcobj_funcptr, &signature, &args))
149 void* pfunc; 152 return PyErr_Format(PyExc_RuntimeError, "argument mismatch");
150 153
151 if (!PyArg_ParseTuple(in_args,"OsO", &pcobj_funcptr, &signature, &args)) 154 pfunc = DcPyCObject_AsVoidPtr(pcobj_funcptr);
152 return PyErr_Format(PyExc_RuntimeError, "argument mismatch"); 155 if (!pfunc)
153 156 return PyErr_Format( PyExc_RuntimeError, "function pointer is NULL" );
154 pfunc = DcPyCObject_AsVoidPtr(pcobj_funcptr); 157
155 if (!pfunc) 158 ptr = signature;
156 return PyErr_Format( PyExc_RuntimeError, "function pointer is NULL" ); 159 pos = 0;
157 160 ts = PyTuple_Size(args);
158 l = PyTuple_Size(args); 161
159 162 dcReset(gpCall);
160 ptr = signature; 163
161 pos = 0; 164 for (ch = *ptr; ch != '\0' && ch != ')'; ch = *++ptr)
162 165 {
163 dcReset(gpCall); 166 PyObject* po;
164 167
165 while ( (ch = *ptr) != '\0' && ch != ')' ) 168 if (pos > ts)
166 { 169 return PyErr_Format( PyExc_RuntimeError, "expecting more arguments" );
167 PyObject* po; 170
168 171 po = PyTuple_GetItem(args, pos);
169 int index = pos+1; 172
170 173 ++pos; // incr here, code below uses it as 1-based argument index for error strings
171 if (pos > l) return PyErr_Format( PyExc_RuntimeError, "expecting more arguments" ); 174
172 175 switch(ch)
173 po = PyTuple_GetItem(args,pos); 176 {
174 177 case DC_SIGCHAR_BOOL:
175 switch(ch) 178 if ( !PyBool_Check(po) )
176 { 179 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting a bool", pos );
177 case DC_SIGCHAR_BOOL: 180 dcArgBool(gpCall, (Py_True == po) ? DC_TRUE : DC_FALSE);
178 { 181 break;
179 DCbool b; 182
180 if ( !PyBool_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a bool", index ); 183 case DC_SIGCHAR_CHAR:
181 b = (Py_True == po) ? DC_TRUE : DC_FALSE; 184 case DC_SIGCHAR_UCHAR:
182 dcArgBool(gpCall, b); 185 {
183 } 186 DCchar c;
184 break; 187 if ( PyUnicode_Check(po) )
185 case DC_SIGCHAR_CHAR: 188 {
186 case DC_SIGCHAR_UCHAR: 189 #if (PY_VERSION_HEX < 0x03030000)
187 { 190 Py_UNICODE cu;
188 DCchar c; 191 if (PyUnicode_GET_SIZE(po) != 1)
189 if ( DcPyString_Check(po) ) 192 #else
190 { 193 Py_UCS4 cu;
191 // Py_ssize_t l; 194 if (PyUnicode_GET_LENGTH(po) != 1)
192 size_t l; 195 #endif
193 char* s; 196 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting a string with length of 1 (a char string)", pos );
194 l = DcPyString_GET_SIZE(po); 197
195 if (l != 1) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a string with length of 1 (a char string)", index ); 198 #if (PY_VERSION_HEX < 0x03030000)
196 s = DcPyString_AsString(po); 199 cu = PyUnicode_AS_UNICODE(po)[0];
197 c = (DCchar) s[0]; 200 #else
198 } 201 cu = PyUnicode_ReadChar(po, 0);
199 else if ( DcPyInt_Check(po) ) 202 #endif
200 { 203 // check against UCHAR_MAX in every case b/c Py_UCS4 is unsigned
201 long l; 204 if ( (cu > UCHAR_MAX))
202 l = DcPyInt_AsLong(po); 205 return PyErr_Format( PyExc_RuntimeError, "arg %d out of range - expecting a char code", pos ); //@@@ error message needs to specify python types
203 if ( (l > CHAR_MAX) || (l < CHAR_MIN)) return PyErr_Format( PyExc_RuntimeError, "value out of range at argument %d - expecting a char code", index ); 206 c = (DCchar) cu;
204 c = (DCchar) l; 207 }
205 } 208 else if ( DcPyString_Check(po) )
206 else return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a char", index ); 209 {
207 dcArgChar(gpCall, c); 210 size_t l;
208 } 211 char* s;
209 break; 212 l = DcPyString_GET_SIZE(po);
210 case DC_SIGCHAR_SHORT: 213 if (l != 1)
211 case DC_SIGCHAR_USHORT: 214 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting a string with length of 1 (a char string)", pos );
212 { 215 s = DcPyString_AsString(po);
213 DCshort s; 216 c = (DCchar) s[0];
214 long v; 217 }
215 if ( !DcPyInt_Check(po) ) 218 else if ( DcPyInt_Check(po) )
216 return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a short int", index ); 219 {
217 v = DcPyInt_AS_LONG(po); 220 long l = DcPyInt_AsLong(po);
218 if ( (v < SHRT_MIN) || (v > SHRT_MAX) ) 221 if (ch == DC_SIGCHAR_CHAR && (l < CHAR_MIN || l > CHAR_MAX))
219 return PyErr_Format( PyExc_RuntimeError, "value out of range at argument %d - expecting a short value", index ); 222 return PyErr_Format( PyExc_RuntimeError, "arg %d out of range - expecting %d <= arg <= %d, got %ld", pos, CHAR_MIN, CHAR_MAX, l );
220 s = (DCshort) v; 223 if (ch == DC_SIGCHAR_UCHAR && (l < 0 || l > UCHAR_MAX))
221 dcArgShort(gpCall, s); 224 return PyErr_Format( PyExc_RuntimeError, "arg %d out of range - expecting 0 <= arg <= %d, got %ld", pos, UCHAR_MAX, l );
222 } 225 c = (DCchar) l;
223 break; 226 }
224 case DC_SIGCHAR_INT: 227 else
225 case DC_SIGCHAR_UINT: 228 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting a char", pos );
226 { 229 dcArgChar(gpCall, c);
227 long v; 230 }
228 if ( !DcPyInt_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting an int", index ); 231 break;
229 v = DcPyInt_AS_LONG(po); 232
230 dcArgInt(gpCall, (DCint) v ); 233 case DC_SIGCHAR_SHORT:
231 } 234 {
232 break; 235 long l;
233 case DC_SIGCHAR_LONG: 236 if ( !DcPyInt_Check(po) )
234 case DC_SIGCHAR_ULONG: 237 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting an int", pos );
235 { 238 l = DcPyInt_AS_LONG(po);
236 long v; 239 if (l < SHRT_MIN || l > SHRT_MAX)
237 if ( !DcPyInt_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting an int", index ); 240 return PyErr_Format( PyExc_RuntimeError, "arg %d out of range - expecting %d <= arg <= %d, got %ld", pos, SHRT_MIN, SHRT_MAX, l );
238 v = DcPyInt_AsLong(po); 241 dcArgShort(gpCall, (DCshort)l);
239 242 }
240 } 243 break;
241 break; 244
242 case DC_SIGCHAR_LONGLONG: 245 case DC_SIGCHAR_USHORT:
243 case DC_SIGCHAR_ULONGLONG: 246 {
244 { 247 long l;
245 PY_LONG_LONG pl; 248 if ( !DcPyInt_Check(po) )
246 DClonglong dl; 249 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting an int", pos );
247 if ( !PyLong_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a long long", index ); 250 l = DcPyInt_AS_LONG(po);
248 pl = PyLong_AsLongLong(po); 251 if (l < 0 || l > USHRT_MAX)
249 dl = (DClonglong) pl; 252 return PyErr_Format( PyExc_RuntimeError, "arg %d out of range - expecting 0 <= arg <= %d, got %ld", pos, USHRT_MAX, l );
250 dcArgLongLong(gpCall, dl ); 253 dcArgShort(gpCall, (DCshort)l);
251 } 254 }
252 break; 255 break;
253 case DC_SIGCHAR_FLOAT: 256
254 { 257 case DC_SIGCHAR_INT:
255 DCfloat f; 258 case DC_SIGCHAR_UINT:
256 if (!PyFloat_Check(po)) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expeecting a float", index ); 259 if ( !DcPyInt_Check(po) )
257 f = (float) PyFloat_AsDouble(po); 260 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting an int", pos );
258 dcArgFloat(gpCall, f); 261 dcArgInt(gpCall, (DCint) DcPyInt_AS_LONG(po));
259 } 262 break;
260 break; 263
261 case DC_SIGCHAR_DOUBLE: 264 case DC_SIGCHAR_LONG:
262 { 265 case DC_SIGCHAR_ULONG:
263 double d; 266 if ( !DcPyInt_Check(po) )
264 if (!PyFloat_Check(po)) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expeecting a float", index ); 267 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting an int", pos );
265 d = PyFloat_AsDouble(po); 268 dcArgLong(gpCall, (DClong) PyLong_AsLong(po));
266 dcArgDouble(gpCall, d); 269 break;
267 } 270
268 break; 271 case DC_SIGCHAR_LONGLONG:
269 case DC_SIGCHAR_POINTER: 272 case DC_SIGCHAR_ULONGLONG:
270 { 273 #if PY_MAJOR_VERSION < 3
271 DCpointer p; 274 if ( PyInt_Check(po) )
272 if ( PyUnicode_Check(po) ) { 275 dcArgLongLong(gpCall, (DClonglong) PyInt_AS_LONG(po));
273 PyObject* bo = PyUnicode_AsEncodedString(po, "utf-8", "strict"); // Owned reference @@@ 276 else
274 if (bo) { 277 #endif
275 p = PyBytes_AS_STRING(bo); // Borrowed pointer 278 if ( !PyLong_Check(po) )
276 //p = strdup(my_result); 279 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting " EXPECT_LONG_TYPE_STR, pos );
277 //Py_DECREF(bo); 280 dcArgLongLong(gpCall, (DClonglong)PyLong_AsLongLong(po));
278 } 281 break;
279 } else if ( DcPyString_Check(po) ) { 282
280 p = (DCpointer) DcPyString_AsString(po); 283 case DC_SIGCHAR_FLOAT:
281 } else if ( PyLong_Check(po) ) { 284 if (!PyFloat_Check(po))
282 p = (DCpointer) PyLong_AsVoidPtr(po); 285 return PyErr_Format( PyExc_RuntimeError, "arg %d - expeecting a float", pos );
283 } else { 286 dcArgFloat(gpCall, (float)PyFloat_AsDouble(po));
284 return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a promoting pointer-type (int,string)", index ); 287 break;
285 } 288
286 dcArgPointer(gpCall, p); 289 case DC_SIGCHAR_DOUBLE:
287 } 290 if (!PyFloat_Check(po))
288 break; 291 return PyErr_Format( PyExc_RuntimeError, "arg %d - expeecting a float", pos );
289 case DC_SIGCHAR_STRING: 292 dcArgDouble(gpCall, PyFloat_AsDouble(po));
290 { 293 break;
291 const char* p; 294
292 if ( PyUnicode_Check(po) ) { 295 case DC_SIGCHAR_POINTER:
293 PyObject* bo = PyUnicode_AsEncodedString(po, "utf-8", "strict"); // Owned reference @@@ 296 {
294 if (bo) { 297 DCpointer p;
295 p = PyBytes_AS_STRING(bo); // Borrowed pointer 298 if ( PyUnicode_Check(po) ) {
296 //p = strdup(my_result); 299 PyObject* bo = PyUnicode_AsEncodedString(po, "utf-8", "strict"); // Owned reference @@@
297 //Py_DECREF(bo); 300 if (bo) {
298 } 301 p = PyBytes_AS_STRING(bo); // Borrowed pointer
299 } else if ( DcPyString_Check(po) ) { 302 //p = strdup(my_result);
300 p = DcPyString_AsString(po); 303 //Py_DECREF(bo);
301 } else { 304 }
302 return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a string", index ); 305 } else if ( DcPyString_Check(po) )
303 } 306 p = (DCpointer) DcPyString_AsString(po);
304 dcArgPointer(gpCall, (DCpointer) p); 307 #if PY_MAJOR_VERSION < 3
305 } 308 else if ( PyInt_Check(po) )
306 break; 309 p = (DCpointer) PyInt_AS_LONG(po);
307 default: return PyErr_Format( PyExc_RuntimeError, "unknown signature character '%c'", ch); 310 #endif
308 } 311 else if ( PyLong_Check(po) )
309 312 p = (DCpointer) PyLong_AsVoidPtr(po);
310 ++pos; ++ptr; 313 else
311 314 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting a promoting pointer-type (int,string)", pos ); //@@@ error message needs to specify python types
312 } 315 dcArgPointer(gpCall, p);
313 316 }
314 if (pos != l) return PyErr_Format( PyExc_RuntimeError, "too many arguments"); 317 break;
315 318
316 if (ch == '\0') return PyErr_Format( PyExc_RuntimeError, "return value missing in signature"); 319 case DC_SIGCHAR_STRING:
317 320 {
318 ch = *++ptr; 321 const char* p;
319 322 if ( PyUnicode_Check(po) ) {
320 switch(ch) 323 PyObject* bo = PyUnicode_AsEncodedString(po, "utf-8", "strict"); // Owned reference @@@
321 { 324 if (bo) {
322 case DC_SIGCHAR_VOID: dcCallVoid (gpCall, pfunc); Py_RETURN_NONE; 325 p = PyBytes_AS_STRING(bo); // Borrowed pointer
323 case DC_SIGCHAR_BOOL: return Py_BuildValue("i", dcCallBool (gpCall, pfunc)); 326 //p = strdup(my_result);@@@
324 case DC_SIGCHAR_CHAR: return Py_BuildValue("b", dcCallChar (gpCall, pfunc)); 327 //Py_DECREF(bo);@@@
325 case DC_SIGCHAR_UCHAR: return Py_BuildValue("B", dcCallChar (gpCall, pfunc)); 328 }
326 case DC_SIGCHAR_SHORT: return Py_BuildValue("h", dcCallShort (gpCall, pfunc)); 329 } else if ( DcPyString_Check(po) ) {
327 case DC_SIGCHAR_USHORT: return Py_BuildValue("H", dcCallShort (gpCall, pfunc)); 330 p = DcPyString_AsString(po);
328 case DC_SIGCHAR_INT: return Py_BuildValue("i", dcCallInt (gpCall, pfunc)); 331 } else {
329 case DC_SIGCHAR_UINT: return Py_BuildValue("I", dcCallInt (gpCall, pfunc)); 332 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting a string", pos ); //@@@ error message needs to specify python types
330 case DC_SIGCHAR_LONG: return Py_BuildValue("l", dcCallLong (gpCall, pfunc)); 333 }
331 case DC_SIGCHAR_ULONG: return Py_BuildValue("k", dcCallLong (gpCall, pfunc)); 334 dcArgPointer(gpCall, (DCpointer) p);
332 case DC_SIGCHAR_LONGLONG: return Py_BuildValue("L", dcCallLongLong(gpCall, pfunc)); 335 }
333 case DC_SIGCHAR_ULONGLONG: return Py_BuildValue("K", dcCallLongLong(gpCall, pfunc)); 336 break;
334 case DC_SIGCHAR_FLOAT: return Py_BuildValue("f", dcCallFloat (gpCall, pfunc)); 337
335 case DC_SIGCHAR_DOUBLE: return Py_BuildValue("d", dcCallDouble (gpCall, pfunc)); 338 default:
336 case DC_SIGCHAR_STRING: return Py_BuildValue("s", dcCallPointer (gpCall, pfunc)); 339 return PyErr_Format( PyExc_RuntimeError, "unknown signature character '%c'", ch);
337 case DC_SIGCHAR_POINTER: return Py_BuildValue("n", dcCallPointer (gpCall, pfunc)); // @@@test, this used to be 'p' which doesn't exist, 'n' is for "Py_ssize_t" 340 }
338 default: return PyErr_Format(PyExc_RuntimeError, "invalid return type signature"); 341 }
339 } 342
343 if (pos != ts)
344 return PyErr_Format( PyExc_RuntimeError, "too many arguments");
345
346 if (ch == '\0')
347 return PyErr_Format( PyExc_RuntimeError, "return value missing in signature");
348
349
350 ch = *++ptr;
351 switch(ch)
352 {
353 case DC_SIGCHAR_VOID: dcCallVoid (gpCall, pfunc); Py_RETURN_NONE;
354 case DC_SIGCHAR_BOOL: return dcCallBool (gpCall, pfunc)?Py_True:Py_False;
355 case DC_SIGCHAR_CHAR: return Py_BuildValue("b", dcCallChar (gpCall, pfunc));
356 case DC_SIGCHAR_UCHAR: return Py_BuildValue("B", dcCallChar (gpCall, pfunc));
357 case DC_SIGCHAR_SHORT: return Py_BuildValue("h", dcCallShort (gpCall, pfunc));
358 case DC_SIGCHAR_USHORT: return Py_BuildValue("H", dcCallShort (gpCall, pfunc));
359 case DC_SIGCHAR_INT: return Py_BuildValue("i", dcCallInt (gpCall, pfunc));
360 case DC_SIGCHAR_UINT: return Py_BuildValue("I", dcCallInt (gpCall, pfunc));
361 case DC_SIGCHAR_LONG: return Py_BuildValue("l", dcCallLong (gpCall, pfunc));
362 case DC_SIGCHAR_ULONG: return Py_BuildValue("k", dcCallLong (gpCall, pfunc));
363 case DC_SIGCHAR_LONGLONG: return Py_BuildValue("L", dcCallLongLong(gpCall, pfunc));
364 case DC_SIGCHAR_ULONGLONG: return Py_BuildValue("K", dcCallLongLong(gpCall, pfunc));
365 case DC_SIGCHAR_FLOAT: return Py_BuildValue("f", dcCallFloat (gpCall, pfunc));
366 case DC_SIGCHAR_DOUBLE: return Py_BuildValue("d", dcCallDouble (gpCall, pfunc));
367 case DC_SIGCHAR_STRING: return Py_BuildValue("s", dcCallPointer (gpCall, pfunc));
368 case DC_SIGCHAR_POINTER: return Py_BuildValue("n", dcCallPointer (gpCall, pfunc)); // @@@test, this used to be 'p' which doesn't exist, 'n' is for "Py_ssize_t"
369 default: return PyErr_Format(PyExc_RuntimeError, "invalid return type signature");
370 }
340 } 371 }
341 372
342 373
343 374
344 375
360 391
361 392
362 PyMODINIT_FUNC 393 PyMODINIT_FUNC
363 PY_MOD_INIT_FUNC_NAME(void) 394 PY_MOD_INIT_FUNC_NAME(void)
364 { 395 {
365 static PyMethodDef pydcMethods[] = { 396 static PyMethodDef pydcMethods[] = {
366 {"load", pydc_load, METH_VARARGS, "load library"}, 397 {"load", pydc_load, METH_VARARGS, "load library"},
367 {"find", pydc_find, METH_VARARGS, "find symbols"}, 398 {"find", pydc_find, METH_VARARGS, "find symbols"},
368 {"free", pydc_free, METH_VARARGS, "free library"}, 399 {"free", pydc_free, METH_VARARGS, "free library"},
369 {"call", pydc_call, METH_VARARGS, "call function"}, 400 {"call", pydc_call, METH_VARARGS, "call function"},
370 {NULL,NULL,0,NULL} 401 {NULL,NULL,0,NULL}
371 }; 402 };
372 403
373 PyObject* m; 404 PyObject* m;
374 #if PY_MAJOR_VERSION >= 3 405 #if PY_MAJOR_VERSION >= 3
375 static struct PyModuleDef moddef = { PyModuleDef_HEAD_INIT, PYDC_MOD_NAME_STR, PYDC_MOD_DESC_STR, -1, pydcMethods, NULL, NULL, NULL, NULL }; 406 static struct PyModuleDef moddef = { PyModuleDef_HEAD_INIT, PYDC_MOD_NAME_STR, PYDC_MOD_DESC_STR, -1, pydcMethods, NULL, NULL, NULL, NULL };
376 m = PyModule_Create(&moddef); 407 m = PyModule_Create(&moddef);
377 #else 408 #else
378 m = Py_InitModule3(PYDC_MOD_NAME_STR, pydcMethods, PYDC_MOD_DESC_STR); 409 m = Py_InitModule3(PYDC_MOD_NAME_STR, pydcMethods, PYDC_MOD_DESC_STR);
379 #endif 410 #endif
380 411
381 if(m) 412 if(m)
382 gpCall = dcNewCallVM(4096); 413 gpCall = dcNewCallVM(4096); //@@@ one shared callvm for the entire module, this is not reentrant
383 414
384 #if PY_MAJOR_VERSION >= 3 415 #if PY_MAJOR_VERSION >= 3
385 return m; 416 return m;
386 #endif 417 #endif
387 } 418 }
388 419