Mercurial > pub > dyncall > bindings
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 |