]> gerrit.simantics Code Review - simantics/python.git/blob - org.simantics.pythonlink.win32.x86_64/src/sclpy.c
Addition of null value check to getPythonObject()
[simantics/python.git] / org.simantics.pythonlink.win32.x86_64 / src / sclpy.c
1 ///////////////////////////////////////////////////////\r
2 //                                                   //\r
3 //   VTT Technical Research Centre of Finland LTD    //\r
4 //   For internal use only. Do not redistribute.     //\r
5 //                                                   //\r
6 //   Authors:                                        //\r
7 //       Antton Tapani    ext-antton.tapani@vtt.fi   //\r
8 //                                                   //\r
9 //   Last modified by Antton Tapani    9.2016        //\r
10 //                                                   //\r
11 ///////////////////////////////////////////////////////\r
12 \r
13 #include "sclpy.h"\r
14 \r
15 #include <windows.h>\r
16 \r
17 jint throwException( JNIEnv *env, char *className, char *message )\r
18 {\r
19     jclass exClass = (*env)->FindClass( env, className);\r
20     if (exClass == NULL) {\r
21         return 0;\r
22     }\r
23 \r
24     return (*env)->ThrowNew( env, exClass, message );\r
25 }\r
26 \r
27 jint throwIllegalArgumentException( JNIEnv *env, char *message ) {\r
28         return throwException( env, ILLEGAL_ARGUMENT_EXCEPTION, message );\r
29 }\r
30 \r
31 int moduleCount = 0;\r
32 int initCalled = 0;\r
33 int hasNumpy = 0;\r
34 \r
35 JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContextImpl(JNIEnv *env, jobject thisObj) {\r
36         char name[16];\r
37 \r
38         if (!initCalled) {\r
39         Py_Initialize();\r
40         initCalled = 1;\r
41 \r
42         hasNumpy = _import_array();\r
43         hasNumpy = hasNumpy != -1;\r
44         }\r
45 \r
46         sprintf(name, "SCL_%d", ++moduleCount);\r
47 \r
48         {\r
49                 PyObject *module = PyModule_New(name);\r
50                 PyObject *main = PyImport_AddModule("__main__");\r
51 \r
52                 PyDict_Merge(PyModule_GetDict(module), PyModule_GetDict(main), 0);\r
53 \r
54                 return (jlong)module;\r
55         }\r
56 }\r
57 \r
58 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_deleteContextImpl(JNIEnv *env, jobject thisObj, jlong contextID) {\r
59         PyObject *module = (PyObject*)contextID;\r
60         Py_XDECREF(module);\r
61 }\r
62 \r
63 PyObject *getPythonBool(jboolean value) {\r
64         if (value) {\r
65                 Py_RETURN_TRUE;\r
66         }\r
67         else {\r
68                 Py_RETURN_FALSE;\r
69         }\r
70 }\r
71 \r
72 PyObject *getPythonString(JNIEnv *env, jstring string) {\r
73         jsize len = (*env)->GetStringLength(env, string);\r
74         const jchar *chars = (*env)->GetStringChars(env, string, NULL);\r
75 \r
76         PyObject *value = PyUnicode_DecodeUTF16((char*)chars, 2*len, NULL, NULL);\r
77 \r
78         (*env)->ReleaseStringChars(env, string, chars);\r
79         return value;\r
80 }\r
81 \r
82 PyObject *getPythonStringList(JNIEnv *env, jobjectArray value) {\r
83         jsize nitems = (*env)->GetArrayLength(env, value);\r
84         jint *values = (*env)->GetIntArrayElements(env, value, NULL);\r
85         jclass stringClass = (*env)->FindClass(env, STRING_CLASS);\r
86         jint i;\r
87 \r
88         PyObject *result = PyList_New(nitems);\r
89         for (i = 0; i < nitems; i++) {\r
90                 jobject item = (*env)->GetObjectArrayElement(env, value, i);\r
91                 if (item != NULL && (*env)->IsInstanceOf(env, item, stringClass)) {\r
92                         PyList_SetItem(result, i, getPythonString(env, (jstring)item));\r
93                 }\r
94                 else {\r
95                         PyList_SetItem(result, i, Py_None);\r
96                 }\r
97         }\r
98 \r
99         (*env)->ReleaseIntArrayElements(env, value, values, JNI_ABORT);\r
100         return result;\r
101 }\r
102 \r
103 PyObject *getPythonBooleanList(JNIEnv *env, jbooleanArray value) {\r
104         jsize nitems = (*env)->GetArrayLength(env, value);\r
105         jboolean *values = (*env)->GetBooleanArrayElements(env, value, NULL);\r
106         jint i;\r
107 \r
108         PyObject *result = PyList_New(nitems);\r
109         for (i = 0; i < nitems; i++) {\r
110                 PyList_SetItem(result, i, getPythonBool(values[i]));\r
111         }\r
112 \r
113         (*env)->ReleaseBooleanArrayElements(env, value, values, JNI_ABORT);\r
114         return result;\r
115 }\r
116 \r
117 PyObject *getPythonByteArray(JNIEnv *env, jbyteArray value) {\r
118         jint len = (*env)->GetArrayLength(env, value);\r
119         jbyte *values = (*env)->GetByteArrayElements(env, value, NULL);\r
120 \r
121         PyObject *result = PyByteArray_FromStringAndSize(values, len);\r
122 \r
123         (*env)->ReleaseByteArrayElements(env, value, values, JNI_ABORT);\r
124         return result;\r
125 }\r
126 \r
127 PyObject *getPythonIntegerList(JNIEnv *env, jintArray value) {\r
128         jsize nitems = (*env)->GetArrayLength(env, value);\r
129         jint *values = (*env)->GetIntArrayElements(env, value, NULL);\r
130         jint i;\r
131 \r
132         PyObject *result = PyList_New(nitems);\r
133         for (i = 0; i < nitems; i++) {\r
134                 PyList_SetItem(result, i, PyLong_FromLong(values[i]));\r
135         }\r
136 \r
137         (*env)->ReleaseIntArrayElements(env, value, values, JNI_ABORT);\r
138         return result;\r
139 }\r
140 \r
141 PyObject *getPythonLongList(JNIEnv *env, jlongArray value) {\r
142         jsize nitems = (*env)->GetArrayLength(env, value);\r
143         jlong *values = (*env)->GetLongArrayElements(env, value, NULL);\r
144         jint i;\r
145 \r
146         PyObject *result = PyList_New(nitems);\r
147         for (i = 0; i < nitems; i++) {\r
148                 PyList_SetItem(result, i, PyLong_FromLongLong(values[i]));\r
149         }\r
150 \r
151         (*env)->ReleaseLongArrayElements(env, value, values, JNI_ABORT);\r
152         return result;\r
153 }\r
154 \r
155 PyObject *getPythonFloatList(JNIEnv *env, jfloatArray value) {\r
156         jsize nitems = (*env)->GetArrayLength(env, value);\r
157         float *values = (*env)->GetFloatArrayElements(env, value, NULL);\r
158         jint i;\r
159 \r
160         PyObject *result = PyList_New(nitems);\r
161         for (i = 0; i < nitems; i++) {\r
162                 PyList_SetItem(result, i, PyFloat_FromDouble((double)values[i]));\r
163         }\r
164 \r
165         (*env)->ReleaseFloatArrayElements(env, value, values, JNI_ABORT);\r
166         return result;\r
167 }\r
168 \r
169 PyObject *getPythonDoubleList(JNIEnv *env, jdoubleArray value) {\r
170         jsize nitems = (*env)->GetArrayLength(env, value);\r
171         double *values = (*env)->GetDoubleArrayElements(env, value, NULL);\r
172         jint i;\r
173 \r
174         PyObject *result = PyList_New(nitems);\r
175         for (i = 0; i < nitems; i++) {\r
176                 PyList_SetItem(result, i, PyFloat_FromDouble(values[i]));\r
177         }\r
178 \r
179         (*env)->ReleaseDoubleArrayElements(env, value, values, JNI_ABORT);\r
180         return result;\r
181 }\r
182 \r
183 PyObject *getPythonNDArray(JNIEnv *env, jobject value) {\r
184         jclass ndarrayClass = (*env)->FindClass(env, NDARRAY_CLASS);\r
185         jmethodID dimsMethod = (*env)->GetMethodID(env, ndarrayClass, "dims", "()[I");\r
186         jmethodID getValuesMethod = (*env)->GetMethodID(env, ndarrayClass, "getValues", "()[D");\r
187 \r
188         jintArray jdims = (*env)->CallObjectMethod(env, value, dimsMethod);\r
189         jsize ndims = (*env)->GetArrayLength(env, jdims);\r
190         jint *dims = (*env)->GetIntArrayElements(env, jdims, NULL);\r
191 \r
192         jdoubleArray jvalues = (*env)->CallObjectMethod(env, value, getValuesMethod);\r
193         jsize len = (*env)->GetArrayLength(env, jvalues);\r
194         jdouble *values = (*env)->GetDoubleArrayElements(env, jvalues, NULL);\r
195 \r
196         npy_intp *pyDims = (npy_intp*)malloc(ndims * sizeof(npy_intp));\r
197 \r
198         jint i, nelem = ndims > 0 ? 1 : 0;\r
199         for (i = 0; i < ndims; i++) {\r
200                 nelem *= dims[i];\r
201                 pyDims[i] = dims[i];\r
202         }\r
203 \r
204         len = min(len, nelem);\r
205 \r
206         {\r
207                 PyObject *array = PyArray_EMPTY(ndims, pyDims, NPY_DOUBLE, 0);\r
208                 double *data = (double *)PyArray_DATA((PyArrayObject*)array);\r
209 \r
210                 memcpy(data, values, len * sizeof(double));\r
211 \r
212                 free(pyDims);\r
213 \r
214                 (*env)->ReleaseDoubleArrayElements(env, jvalues, values, JNI_ABORT);\r
215                 (*env)->ReleaseIntArrayElements(env, jdims, dims, JNI_ABORT);\r
216 \r
217                 return array;\r
218         }\r
219 }\r
220 \r
221 PyObject *getPythonBooleanObject(JNIEnv *env, jobject object, jobject binding) {\r
222         jclass bindingClass = (*env)->FindClass(env, BOOLEANBINDING_CLASS);\r
223         jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)Z");\r
224 \r
225         jboolean bvalue = (*env)->CallBooleanMethod(env, binding, getValueMethod, object);\r
226         return getPythonBool(bvalue);\r
227 }\r
228 \r
229 PyObject *getPythonByteObject(JNIEnv *env, jobject object, jobject binding) {\r
230         jclass bindingClass = (*env)->FindClass(env, BYTEBINDING_CLASS);\r
231         jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)B");\r
232 \r
233         jbyte v = (*env)->CallByteMethod(env, binding, getValueMethod, object);\r
234         return PyLong_FromLong(v);\r
235 }\r
236 \r
237 PyObject *getPythonIntegerObject(JNIEnv *env, jobject object, jobject binding) {\r
238         jclass bindingClass = (*env)->FindClass(env, INTEGERBINDING_CLASS);\r
239         jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)I");\r
240 \r
241         jint v = (*env)->CallIntMethod(env, binding, getValueMethod, object);\r
242         return PyLong_FromLong(v);\r
243 }\r
244 \r
245 PyObject *getPythonLongObject(JNIEnv *env, jobject object, jobject binding) {\r
246         jclass bindingClass = (*env)->FindClass(env, LONGBINDING_CLASS);\r
247         jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)J");\r
248 \r
249         jlong v = (*env)->CallLongMethod(env, binding, getValueMethod, object);\r
250         return PyLong_FromLongLong(v);\r
251 }\r
252 \r
253 PyObject *getPythonFloatObject(JNIEnv *env, jobject object, jobject binding) {\r
254         jclass bindingClass = (*env)->FindClass(env, FLOATBINDING_CLASS);\r
255         jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)F");\r
256 \r
257         jfloat v = (*env)->CallFloatMethod(env, binding, getValueMethod, object);\r
258         return PyFloat_FromDouble(v);\r
259 }\r
260 \r
261 PyObject *getPythonDoubleObject(JNIEnv *env, jobject object, jobject binding) {\r
262         jclass bindingClass = (*env)->FindClass(env, DOUBLEBINDING_CLASS);\r
263         jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)D");\r
264 \r
265         jdouble v = (*env)->CallDoubleMethod(env, binding, getValueMethod, object);\r
266         return PyFloat_FromDouble(v);\r
267 }\r
268 \r
269 PyObject *getPythonStringObject(JNIEnv *env, jobject object, jobject binding) {\r
270         jclass bindingClass = (*env)->FindClass(env, STRINGBINDING_CLASS);\r
271         jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue", "(L" OBJECT_CLASS ";)L" STRING_CLASS ";");\r
272 \r
273         jobject string = (*env)->CallObjectMethod(env, binding, getValueMethod, object);\r
274         jsize len = (*env)->GetStringLength(env, string);\r
275         const jchar *chars = (*env)->GetStringChars(env, string, NULL);\r
276 \r
277         PyObject *value = PyUnicode_DecodeUTF16((char*)chars, 2*len, NULL, NULL);\r
278 \r
279         (*env)->ReleaseStringChars(env, string, chars);\r
280         return value;\r
281 }\r
282 \r
283 PyObject *getPythonRecordObject(JNIEnv *env, jobject object, jobject binding) {\r
284         jclass bindingClass = (*env)->FindClass(env, RECORDBINDING_CLASS);\r
285         jmethodID typeMethod = (*env)->GetMethodID(env, bindingClass, "type", "()L" RECORDTYPE_CLASS ";");\r
286         jmethodID getComponent = (*env)->GetMethodID(env, bindingClass, "getComponent", "(L" OBJECT_CLASS ";I)L" OBJECT_CLASS ";");\r
287         jmethodID getComponentBinding = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "(I)L" BINDING_CLASS ";");\r
288 \r
289         jclass recordType = (*env)->FindClass(env, RECORDTYPE_CLASS);\r
290         jmethodID getTypeComponent = (*env)->GetMethodID(env, recordType, "getComponent", "(I)L" COMPONENT_CLASS ";");\r
291         jmethodID getComponentCount = (*env)->GetMethodID(env, recordType, "getComponentCount", "()I");\r
292 \r
293         jclass componentClass = (*env)->FindClass(env, COMPONENT_CLASS);\r
294         jfieldID nameField = (*env)->GetFieldID(env, componentClass, "name", "L" STRING_CLASS ";");\r
295 \r
296         jobject type = (*env)->CallObjectMethod(env, binding, typeMethod);\r
297         jint n = (*env)->CallIntMethod(env, type, getComponentCount);\r
298         jint i;\r
299 \r
300         PyObject *result = PyDict_New();\r
301         for (i = 0; i < n; i++) {\r
302                 jobject recordTypeComponent = (*env)->CallObjectMethod(env, type, getComponent, i);\r
303                 jstring fieldName = (jstring)(*env)->GetObjectField(env, recordTypeComponent, nameField);\r
304                 jobject componentObject = (*env)->CallObjectMethod(env, binding, getComponent, object, i);\r
305                 jobject componentBinding = (*env)->CallObjectMethod(env, binding, getComponentBinding, i);\r
306 \r
307                 PyObject *item = getPythonObject(env, componentObject, componentBinding);\r
308                 PyDict_SetItem(result, getPythonString(env, fieldName), item);\r
309         }\r
310 \r
311         return result;\r
312 }\r
313 \r
314 PyObject *getPythonArrayObject(JNIEnv *env, jobject object, jobject binding) {\r
315         jclass bindingClass = (*env)->FindClass(env, ARRAYBINDING_CLASS);\r
316         jmethodID componentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "()L" BINDING_CLASS ";");\r
317         jmethodID sizeMethod = (*env)->GetMethodID(env, bindingClass, "size", "(L" OBJECT_CLASS ";)I");\r
318         jmethodID getMethod = (*env)->GetMethodID(env, bindingClass, "get", "(L" OBJECT_CLASS ";I)L" OBJECT_CLASS ";");\r
319 \r
320         jobject componentBinding = (*env)->CallObjectMethod(env, binding, componentBindingMethod);\r
321 \r
322         jint size = (*env)->CallIntMethod(env, binding, sizeMethod, object);\r
323 \r
324         PyObject *result = PyList_New(size);\r
325 \r
326         jint i;\r
327         for (i = 0; i < size; i++) {\r
328                 jobject item = (*env)->CallObjectMethod(env, binding, getMethod, object, i);\r
329                 if (item != NULL)\r
330                         PyList_SetItem(result, i, getPythonObject(env, item, componentBinding));\r
331                 else\r
332                         PyList_SetItem(result, i, Py_None);\r
333         }\r
334 \r
335         return result;\r
336 }\r
337 \r
338 PyObject *getPythonMapObject(JNIEnv *env, jobject object, jobject binding) {\r
339         jclass objectClass = (*env)->FindClass(env, OBJECT_CLASS);\r
340         jclass bindingClass = (*env)->FindClass(env, MAPBINDING_CLASS);\r
341         jmethodID getKeyBindingMethod = (*env)->GetMethodID(env, bindingClass, "getKeyBinding", "()L" BINDING_CLASS ";");\r
342         jmethodID getValueBindingMethod = (*env)->GetMethodID(env, bindingClass, "getValueBinding", "()L" BINDING_CLASS ";");\r
343         jmethodID sizeMethod = (*env)->GetMethodID(env, bindingClass, "size", "(L" OBJECT_CLASS ";)I");\r
344         jmethodID getAllMethod = (*env)->GetMethodID(env, bindingClass, "getAll", "(L" OBJECT_CLASS ";[L" OBJECT_CLASS ";[L" OBJECT_CLASS ";)V");\r
345 \r
346         jobject keyBinding = (*env)->CallObjectMethod(env, binding, getKeyBindingMethod);\r
347         jobject valueBinding = (*env)->CallObjectMethod(env, binding, getValueBindingMethod);\r
348 \r
349         jint size = (*env)->CallIntMethod(env, binding, sizeMethod, object);\r
350         jobjectArray keys = (*env)->NewObjectArray(env, size, objectClass, NULL);\r
351         jobjectArray values = (*env)->NewObjectArray(env, size, objectClass, NULL);\r
352 \r
353         PyObject *result = PyDict_New();\r
354         jint i;\r
355 \r
356         (*env)->CallVoidMethod(env, binding, getAllMethod, object, keys, values);\r
357 \r
358         for (i = 0; i < size; i++) {\r
359                 jobject key = (*env)->GetObjectArrayElement(env, keys, i);\r
360                 jobject item = (*env)->GetObjectArrayElement(env, values, i);\r
361                 PyDict_SetItem(result, getPythonObject(env, key, keyBinding), getPythonObject(env, item, valueBinding));\r
362         }\r
363 \r
364         (*env)->DeleteLocalRef(env, keys);\r
365         (*env)->DeleteLocalRef(env, values);\r
366 \r
367         return result;\r
368 }\r
369 \r
370 PyObject *getPythonOptionalObject(JNIEnv *env, jobject object, jobject binding) {\r
371         jclass bindingClass = (*env)->FindClass(env, OPTIONALBINDING_CLASS);\r
372         jmethodID hasValueMethod = (*env)->GetMethodID(env, bindingClass, "hasValue", "(L" OBJECT_CLASS ";)Z");\r
373 \r
374         jboolean hasValue = (*env)->CallBooleanMethod(env, binding, hasValueMethod, object);\r
375 \r
376         if (hasValue) {\r
377                 jmethodID componentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "()L" BINDING_CLASS ";");\r
378                 jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "hasValue", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");\r
379 \r
380                 jobject componentBinding = (*env)->CallObjectMethod(env, binding, componentBindingMethod);\r
381                 jobject value = (*env)->CallObjectMethod(env, binding, getValueMethod, object);\r
382 \r
383                 return getPythonObject(env, value, componentBinding);\r
384         }\r
385         else {\r
386                 return Py_None;\r
387         }\r
388 }\r
389 \r
390 PyObject *getPythonUnionObject(JNIEnv *env, jobject object, jobject binding) {\r
391         jclass bindingClass = (*env)->FindClass(env, UNIONBINDING_CLASS);\r
392         jmethodID typeMethod = (*env)->GetMethodID(env, bindingClass, "type", "()L" RECORDTYPE_CLASS ";");\r
393         jmethodID getTagMethod = (*env)->GetMethodID(env, bindingClass, "getTag", "(L" OBJECT_CLASS ";)I");\r
394         jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");\r
395         jmethodID getComponentBinding = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "(I)L" BINDING_CLASS ";");\r
396 \r
397         jclass unionType = (*env)->FindClass(env, UNIONTYPE_CLASS);\r
398         jmethodID getTypeComponent = (*env)->GetMethodID(env, unionType, "getComponent", "(I)L" COMPONENT_CLASS ";");\r
399 \r
400         jclass componentClass = (*env)->FindClass(env, COMPONENT_CLASS);\r
401         jfieldID nameField = (*env)->GetFieldID(env, componentClass, "name", "L" STRING_CLASS ";");\r
402 \r
403         jint tag = (*env)->CallIntMethod(env, binding, getTagMethod, object);\r
404         jobject value = (*env)->CallObjectMethod(env, binding, getValueMethod, object);\r
405 \r
406         jobject type = (*env)->CallObjectMethod(env, binding, typeMethod);\r
407         jobject typeComponent = (*env)->CallObjectMethod(env, type, getTypeComponent, tag);\r
408         jstring compName = (*env)->GetObjectField(env, typeComponent, nameField);\r
409 \r
410         jobject componentBinding = (*env)->CallObjectMethod(env, binding, getComponentBinding, tag);\r
411 \r
412         PyObject *result = PyTuple_New(2);\r
413         PyTuple_SetItem(result, 0, getPythonString(env, compName));\r
414         PyTuple_SetItem(result, 1, getPythonObject(env, value, componentBinding));\r
415 \r
416         return result;\r
417 }\r
418 \r
419 PyObject *getPythonVariantObject(JNIEnv *env, jobject object, jobject binding) {\r
420         jclass bindingClass = (*env)->FindClass(env, VARIANTBINDING_CLASS);\r
421         jmethodID getContentMethod = (*env)->GetMethodID(env, bindingClass, "getContent", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");\r
422         jmethodID getContentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getContentBinding", "(L" OBJECT_CLASS ";)L" BINDING_CLASS ";");\r
423 \r
424         jobject content = (*env)->CallObjectMethod(env, binding, getContentMethod, object);\r
425         jobject contentBinding = (*env)->CallObjectMethod(env, binding, getContentBindingMethod, object);\r
426 \r
427         return getPythonObject(env, content, contentBinding);\r
428 }\r
429 \r
430 PyObject *getPythonObject(JNIEnv *env, jobject value, jobject binding) {\r
431         jclass booleanBinding = (*env)->FindClass(env, BOOLEANBINDING_CLASS);\r
432         jclass byteBinding = (*env)->FindClass(env, BYTEBINDING_CLASS);\r
433         jclass integerBinding = (*env)->FindClass(env, INTEGERBINDING_CLASS);\r
434         jclass longBinding = (*env)->FindClass(env, LONGBINDING_CLASS);\r
435         jclass floatBinding = (*env)->FindClass(env, FLOATBINDING_CLASS);\r
436         jclass doubleBinding = (*env)->FindClass(env, DOUBLEBINDING_CLASS);\r
437         jclass stringBinding = (*env)->FindClass(env, STRINGBINDING_CLASS);\r
438         jclass recordBinding = (*env)->FindClass(env, RECORDBINDING_CLASS);\r
439         jclass arrayBinding = (*env)->FindClass(env, ARRAYBINDING_CLASS);\r
440         jclass mapBinding = (*env)->FindClass(env, MAPBINDING_CLASS);\r
441         jclass optionalBinding = (*env)->FindClass(env, OPTIONALBINDING_CLASS);\r
442         jclass untionBinding = (*env)->FindClass(env, UNIONBINDING_CLASS);\r
443         jclass variantBinding = (*env)->FindClass(env, VARIANTBINDING_CLASS);\r
444 \r
445         if (value == NULL)\r
446                 return Py_None;\r
447 \r
448         if ((*env)->IsInstanceOf(env, binding, booleanBinding)) {\r
449                 return getPythonBooleanObject(env, value, binding);\r
450         }\r
451         else if ((*env)->IsInstanceOf(env, binding, byteBinding)) {\r
452                 return getPythonByteObject(env, value, binding);\r
453         }\r
454         else if ((*env)->IsInstanceOf(env, binding, integerBinding)) {\r
455                 return getPythonIntegerObject(env, value, binding);\r
456         }\r
457         else if ((*env)->IsInstanceOf(env, binding, longBinding)) {\r
458                 return getPythonLongObject(env, value, binding);\r
459         }\r
460         else if ((*env)->IsInstanceOf(env, binding, floatBinding)) {\r
461                 return getPythonFloatObject(env, value, binding);\r
462         }\r
463         else if ((*env)->IsInstanceOf(env, binding, doubleBinding)) {\r
464                 return getPythonDoubleObject(env, value, binding);\r
465         }\r
466         else if ((*env)->IsInstanceOf(env, binding, stringBinding)) {\r
467                 return getPythonStringObject(env, value, binding);\r
468         }\r
469         else if ((*env)->IsInstanceOf(env, binding, recordBinding)) {\r
470                 return getPythonRecordObject(env, value, binding);\r
471         }\r
472         else if ((*env)->IsInstanceOf(env, binding, arrayBinding)) {\r
473                 return getPythonArrayObject(env, value, binding);\r
474         }\r
475         else if ((*env)->IsInstanceOf(env, binding, mapBinding)) {\r
476                 return getPythonMapObject(env, value, binding);\r
477         }\r
478         else if ((*env)->IsInstanceOf(env, binding, optionalBinding)) {\r
479                 return getPythonOptionalObject(env, value, binding);\r
480         }\r
481         else if ((*env)->IsInstanceOf(env, binding, untionBinding)) {\r
482                 return getPythonUnionObject(env, value, binding);\r
483         }\r
484         else if ((*env)->IsInstanceOf(env, binding, variantBinding)) {\r
485                 return getPythonVariantObject(env, value, binding);\r
486         }\r
487         else {\r
488                 return Py_None;\r
489         }\r
490 }\r
491 \r
492 void setPythonVariable(PyObject *module, PyObject *name, PyObject *value) {\r
493         if (name && value) {\r
494                 PyDict_SetItem(PyModule_GetDict(module), name, value);\r
495         }\r
496 \r
497         Py_XDECREF(name);\r
498         Py_XDECREF(value);\r
499 }\r
500 \r
501 static npy_intp nContiguous(int d, int nd, npy_intp *strides, npy_intp *dims, npy_intp *ncont) {\r
502         if (d == nd) {\r
503                 ncont[d] = 1;\r
504                 return 1;\r
505         }\r
506         else {\r
507                 npy_intp n = nContiguous(d+1, nd, strides, dims, ncont);\r
508                 ncont[d] = n > 0 && strides[d] == sizeof(double) * n ? dims[d] * n : 0;\r
509                 return ncont[d];\r
510         }\r
511 }\r
512 \r
513 static void copyDoubleArrayValues(JNIEnv *env, jdoubleArray array, double *data, npy_intp *offset, int d, int nd, npy_intp *strides, npy_intp *dims, npy_intp *ncont) {\r
514         if (ncont[d] > 0) {\r
515                 (*env)->SetDoubleArrayRegion(env, array, (jint)*offset, (jint)ncont[d], data);\r
516                 *offset += ncont[d];\r
517         }\r
518         else {\r
519                 int i;\r
520                 for (i = 0; i < dims[d]; i++) {\r
521                         copyDoubleArrayValues(env, array, (double*)((char*)data + strides[d] * i), offset, d+1, nd, strides, dims, ncont);\r
522                 }\r
523         }\r
524 }\r
525 \r
526 jobject pythonBoolAsBooleanObject(JNIEnv *env, PyObject *value) {\r
527         jclass booleanClass = (*env)->FindClass(env, "java/lang/Boolean");\r
528         jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, booleanClass, "valueOf", "(Z)Ljava/lang/Boolean;");\r
529 \r
530         return (*env)->CallStaticObjectMethod(env, booleanClass, valueOfMethod, (jboolean)(value == Py_True));\r
531 }\r
532 \r
533 jobject pythonLongAsLongObject(JNIEnv *env, PyObject *value) {\r
534         jclass longClass = (*env)->FindClass(env, "java/lang/Long");\r
535         jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, longClass, "valueOf", "(J)Ljava/lang/Long;");\r
536 \r
537         return (*env)->CallStaticObjectMethod(env, longClass, valueOfMethod, PyLong_AsLongLong(value));\r
538 }\r
539 \r
540 jobject pythonFloatAsDoubleObject(JNIEnv *env, PyObject *value) {\r
541         jclass doubleClass = (*env)->FindClass(env, "java/lang/Double");\r
542         jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, doubleClass, "valueOf", "(D)Ljava/lang/Double;");\r
543 \r
544         return (*env)->CallStaticObjectMethod(env, doubleClass, valueOfMethod, PyFloat_AsDouble(value));\r
545 }\r
546 \r
547 jobject pythonByteArrayAsByteArray(JNIEnv *env, PyObject *value) {\r
548         Py_ssize_t size = PyByteArray_Size(value);\r
549         jbyteArray result = (*env)->NewByteArray(env, (jsize)size);\r
550         char *bytes = PyByteArray_AsString(value);\r
551 \r
552         (*env)->SetByteArrayRegion(env, result, 0, size, bytes);\r
553 \r
554         return result;\r
555 }\r
556 \r
557 jstring pythonStringAsJavaString(JNIEnv *env, PyObject *string) {\r
558         PyObject *utf16Value = PyUnicode_AsUTF16String(string);\r
559         Py_ssize_t len = PyBytes_Size(utf16Value) / 2;\r
560         char *bytes = PyBytes_AsString(utf16Value);\r
561 \r
562         // Create Java string, skipping the byte order mark in the beginning\r
563         jstring result = (*env)->NewString(env, (jchar *)bytes + 1, (jsize)min(len, JAVA_MAXINT) - 1);\r
564 \r
565         Py_XDECREF(utf16Value);\r
566 \r
567         return result;\r
568 }\r
569 \r
570 jobjectArray pythonSequenceAsStringArray(JNIEnv *env, PyObject *seq) {\r
571         Py_ssize_t len = PySequence_Size(seq);\r
572         jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
573         jobjectArray array = (*env)->NewObjectArray(env, jlen, (*env)->FindClass(env, STRING_CLASS), NULL);\r
574 \r
575         jint i;\r
576 \r
577         for (i = 0; i < jlen; i++) {\r
578                 PyObject *item = PySequence_GetItem(seq, i);\r
579                 if (PyUnicode_Check(item)) {\r
580                         jstring value = pythonStringAsJavaString(env, item);\r
581                         (*env)->SetObjectArrayElement(env, array, i, value);\r
582                 }\r
583                 else {\r
584                         throwException(env, RUNTIME_EXCEPTION, "List item not a string");\r
585                         return NULL;\r
586                 }\r
587         }\r
588 \r
589         return array;\r
590 }\r
591 \r
592 jdoubleArray pythonSequenceAsDoubleArray(JNIEnv *env, PyObject *seq) {\r
593         Py_ssize_t len = PySequence_Size(seq);\r
594         jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
595         jdoubleArray array = (*env)->NewDoubleArray(env, jlen);\r
596 \r
597         jint i;\r
598 \r
599         for (i = 0; i < jlen; i++) {\r
600                 PyObject *item = PySequence_GetItem(seq, i);\r
601                 if (PyFloat_Check(item)) {\r
602                         double value = PyFloat_AsDouble(item);\r
603                         (*env)->SetDoubleArrayRegion(env, array, i, 1, &value);\r
604                 }\r
605                 else {\r
606                         throwException(env, RUNTIME_EXCEPTION, "List item not a floating point value");\r
607                         return NULL;\r
608                 }\r
609         }\r
610 \r
611         return array;\r
612 }\r
613 \r
614 jobject pythonObjectAsObject(JNIEnv *env, PyObject *value) {\r
615         if (PyBool_Check(value))\r
616                 return pythonBoolAsBooleanObject(env, value);\r
617         else if (PyLong_Check(value))\r
618                 return pythonLongAsLongObject(env, value);\r
619         else if (PyFloat_Check(value))\r
620                 return pythonFloatAsDoubleObject(env, value);\r
621         else if (PyUnicode_Check(value))\r
622                 return pythonStringAsJavaString(env, value);\r
623         else if (PyByteArray_Check(value))\r
624                 return pythonByteArrayAsByteArray(env, value);\r
625         else if (PyDict_Check(value))\r
626                 return pythonDictionaryAsMap(env, value);\r
627         else if (hasNumpy && PyArray_Check(value))\r
628                 return pythonArrayAsNDArray(env, (PyArrayObject *)value);\r
629         else if (PySequence_Check(value))\r
630                 return pythonSequenceAsObjectArray(env, value);\r
631         else\r
632                 return NULL;\r
633 }\r
634 \r
635 jobjectArray pythonSequenceAsObjectArray(JNIEnv *env, PyObject *seq) {\r
636         Py_ssize_t len = PySequence_Size(seq);\r
637         jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
638         jobjectArray array = (*env)->NewObjectArray(env, jlen, (*env)->FindClass(env, OBJECT_CLASS), NULL);\r
639 \r
640         jint i;\r
641 \r
642         for (i = 0; i < jlen; i++) {\r
643                 PyObject *item = PySequence_GetItem(seq, i);\r
644                 jobject object = pythonObjectAsObject(env, item);\r
645                 (*env)->SetObjectArrayElement(env, array, i, object);\r
646         }\r
647 \r
648         return array;\r
649 }\r
650 \r
651 jbooleanArray pythonSequenceAsBooleanArray(JNIEnv *env, PyObject *seq) {\r
652         Py_ssize_t len = PySequence_Size(seq);\r
653         jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
654         jbooleanArray array = (*env)->NewBooleanArray(env, jlen);\r
655 \r
656         jint i;\r
657 \r
658         for (i = 0; i < jlen; i++) {\r
659                 PyObject *item = PySequence_GetItem(seq, i);\r
660                 if (PyBool_Check(item)) {\r
661                         jboolean value = item == Py_True;\r
662                         (*env)->SetBooleanArrayRegion(env, array, i, 1, &value);\r
663                 }\r
664                 else {\r
665                         throwException(env, RUNTIME_EXCEPTION, "List item not a boolean");\r
666                         return NULL;\r
667                 }\r
668         }\r
669 \r
670         return array;\r
671 }\r
672 \r
673 jintArray pythonSequenceAsIntegerArray(JNIEnv *env, PyObject *seq) {\r
674         Py_ssize_t len = PySequence_Size(seq);\r
675         jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
676         jintArray array = (*env)->NewIntArray(env, jlen);\r
677 \r
678         jint i;\r
679 \r
680         for (i = 0; i < jlen; i++) {\r
681                 PyObject *item = PySequence_GetItem(seq, i);\r
682                 if (PyLong_Check(item)) {\r
683                         jint value = PyLong_AsLong(item);\r
684                         (*env)->SetIntArrayRegion(env, array, i, 1, &value);\r
685                 }\r
686                 else {\r
687                         throwException(env, RUNTIME_EXCEPTION, "List item not an integer");\r
688                         return NULL;\r
689                 }\r
690         }\r
691 \r
692         return array;\r
693 }\r
694 \r
695 jlongArray pythonSequenceAsLongArray(JNIEnv *env, PyObject *seq) {\r
696         Py_ssize_t len = PySequence_Size(seq);\r
697         jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
698         jlongArray array = (*env)->NewLongArray(env, jlen);\r
699 \r
700         jint i;\r
701 \r
702         for (i = 0; i < jlen; i++) {\r
703                 PyObject *item = PySequence_GetItem(seq, i);\r
704                 if (PyLong_Check(item)) {\r
705                         jlong value = PyLong_AsLongLong(item);\r
706                         (*env)->SetLongArrayRegion(env, array, i, 1, &value);\r
707                 }\r
708                 else {\r
709                         throwException(env, RUNTIME_EXCEPTION, "List item not an integer");\r
710                         return NULL;\r
711                 }\r
712         }\r
713 \r
714         return array;\r
715 }\r
716 \r
717 jobject pythonArrayAsNDArray(JNIEnv *env, PyArrayObject *array) {\r
718         jclass ndarrayClass = (*env)->FindClass(env, NDARRAY_CLASS);\r
719         jmethodID constructor = (*env)->GetMethodID(env, ndarrayClass, "<init>", "([I[D)V");\r
720 \r
721         int ndims = PyArray_NDIM(array);\r
722         npy_intp *dims = PyArray_DIMS(array);\r
723 \r
724         npy_intp len = PyArray_Size((PyObject*)array);\r
725         double *values = (double*)PyArray_DATA(array);\r
726 \r
727         jboolean isFortran = PyArray_ISFORTRAN(array) != 0;\r
728 \r
729         int i;\r
730 \r
731         if (len > JAVA_MAXINT) {\r
732                 throwException(env, RUNTIME_EXCEPTION, "Array too large");\r
733                 return NULL;\r
734         }\r
735 \r
736         {\r
737                 jintArray jdims = (*env)->NewIntArray(env, ndims);\r
738                 jdoubleArray jvalues = (*env)->NewDoubleArray(env, (jsize)len);\r
739 \r
740                 for (i = 0; i < ndims; i++) {\r
741                         jint dim = (jint)dims[i];\r
742                         (*env)->SetIntArrayRegion(env, jdims, i, 1, &dim);\r
743                 }\r
744 \r
745                 if (PyArray_IS_C_CONTIGUOUS(array)) {\r
746                         (*env)->SetDoubleArrayRegion(env, jvalues, 0, (jsize)len, values);\r
747                 }\r
748                 else {\r
749                         npy_intp offset = 0;\r
750                         npy_intp *strides = PyArray_STRIDES(array);\r
751                         npy_intp *ncont = (npy_intp*)malloc((ndims + 1) * sizeof(npy_intp));\r
752                         nContiguous(0, ndims, strides, dims, ncont);\r
753                         copyDoubleArrayValues(env, jvalues, values, &offset, 0, ndims, strides, dims, ncont);\r
754                         free(ncont);\r
755                 }\r
756 \r
757                 return (*env)->NewObject(env, ndarrayClass, constructor, jdims, jvalues, isFortran);\r
758         }\r
759 }\r
760 \r
761 jobject pythonDictionaryAsMap(JNIEnv *env, PyObject *dict) {\r
762         jclass hashmapClass = (*env)->FindClass(env, "java/util/HashMap");\r
763         jmethodID constructor = (*env)->GetMethodID(env, hashmapClass, "<init>", "(I)V");\r
764         jmethodID putMethod = (*env)->GetMethodID(env, hashmapClass, "put", "(L" OBJECT_CLASS ";L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");\r
765 \r
766         Py_ssize_t size = PyDict_Size(dict);\r
767         jobject map = (*env)->NewObject(env, hashmapClass, constructor, (jint)size);\r
768 \r
769         PyObject *key, *value;\r
770         Py_ssize_t pos = 0;\r
771 \r
772         while (PyDict_Next(dict, &pos, &key, &value)) {\r
773                 jobject keyObject = pythonObjectAsObject(env, key);\r
774                 jobject valueObject = pythonObjectAsObject(env, value);\r
775                 (*env)->CallObjectMethod(env, map, putMethod, keyObject, valueObject);\r
776         }\r
777 \r
778         return map;\r
779 }\r
780 \r
781 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBooleanVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jboolean value) {\r
782         PyObject *module = (PyObject*)contextID;\r
783 \r
784         PyObject *pythonName = getPythonString(env, variableName);\r
785         PyObject *val = getPythonBool(value);\r
786 \r
787         setPythonVariable(module, pythonName, val);\r
788 }\r
789 \r
790 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBooleanArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jbooleanArray value) {\r
791         PyObject *module = (PyObject*)contextID;\r
792 \r
793         PyObject *pythonName = getPythonString(env, variableName);\r
794         PyObject *val = getPythonBooleanList(env, value);\r
795 \r
796         setPythonVariable(module, pythonName, val);\r
797 }\r
798 \r
799 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonLongVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jlong value) {\r
800         PyObject *module = (PyObject*)contextID;\r
801 \r
802         PyObject *pythonName = getPythonString(env, variableName);\r
803         PyObject *val = PyLong_FromLongLong(value);\r
804 \r
805         setPythonVariable(module, pythonName, val);\r
806 }\r
807 \r
808 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jintArray value) {\r
809         PyObject *module = (PyObject*)contextID;\r
810 \r
811         PyObject *pythonName = getPythonString(env, variableName);\r
812         PyObject *val = getPythonIntegerList(env, value);\r
813 \r
814         setPythonVariable(module, pythonName, val);\r
815 }\r
816 \r
817 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonLongArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jlongArray value) {\r
818         PyObject *module = (PyObject*)contextID;\r
819 \r
820         PyObject *pythonName = getPythonString(env, variableName);\r
821         PyObject *val = getPythonLongList(env, value);\r
822 \r
823         setPythonVariable(module, pythonName, val);\r
824 }\r
825 \r
826 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdouble value) {\r
827         PyObject *module = (PyObject*)contextID;\r
828 \r
829         PyObject *pythonName = getPythonString(env, variableName);\r
830         PyObject *val = PyFloat_FromDouble(value);\r
831 \r
832         setPythonVariable(module, pythonName, val);\r
833 }\r
834 \r
835 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonFloatArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jfloatArray value) {\r
836         PyObject *module = (PyObject*)contextID;\r
837 \r
838         PyObject *pythonName = getPythonString(env, variableName);\r
839         PyObject *val = getPythonFloatList(env, value);\r
840 \r
841         setPythonVariable(module, pythonName, val);\r
842 }\r
843 \r
844 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdoubleArray value) {\r
845         PyObject *module = (PyObject*)contextID;\r
846 \r
847         PyObject *pythonName = getPythonString(env, variableName);\r
848         PyObject *val = getPythonDoubleList(env, value);\r
849 \r
850         setPythonVariable(module, pythonName, val);\r
851 }\r
852 \r
853 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jstring value) {\r
854         PyObject *module = (PyObject*)contextID;\r
855 \r
856         PyObject *pythonName = getPythonString(env, variableName);\r
857         PyObject *val = getPythonString(env, value);\r
858 \r
859         setPythonVariable(module, pythonName, val);\r
860 }\r
861 \r
862 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobjectArray value) {\r
863         PyObject *module = (PyObject*)contextID;\r
864 \r
865         PyObject *pythonName = getPythonString(env, variableName);\r
866         PyObject *val = getPythonStringList(env, value);\r
867 \r
868         setPythonVariable(module, pythonName, val);\r
869 }\r
870 \r
871 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value) {\r
872         PyObject *module = (PyObject*)contextID;\r
873 \r
874         if (!hasNumpy) {\r
875                 throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed");\r
876                 return;\r
877         }\r
878 \r
879         {\r
880                 PyObject *pythonName = getPythonString(env, variableName);\r
881                 PyObject *val = getPythonNDArray(env, value);\r
882 \r
883                 setPythonVariable(module, pythonName, val);\r
884         }\r
885 }\r
886 \r
887 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonVariantVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value, jobject binding) {\r
888         PyObject *module = (PyObject*)contextID;\r
889 \r
890         PyObject *pythonName = getPythonString(env, variableName);\r
891         PyObject *val = getPythonObject(env, value, binding);\r
892 \r
893         setPythonVariable(module, pythonName, val);\r
894 }\r
895 \r
896 JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePythonStatementImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring statement) {\r
897         PyObject *module = (PyObject*)contextID;\r
898 \r
899         const char *utfchars = (*env)->GetStringUTFChars(env, statement, NULL);\r
900 \r
901         PyErr_Clear();\r
902         {\r
903                 PyObject *globals;\r
904 \r
905                 globals = PyModule_GetDict(module);\r
906 \r
907                 {\r
908                         PyObject *result = PyRun_String(utfchars, Py_file_input, globals, globals);\r
909 \r
910                         PyObject *exceptionType = PyErr_Occurred();\r
911                         if (exceptionType != NULL) {\r
912                                 PyObject *exception, *stackTrace;\r
913                                 char *message;\r
914                                 PyErr_Fetch(&exceptionType, &exception, &stackTrace);\r
915                                 message = PyUnicode_AsUTF8(exception);\r
916                                 throwException(env, RUNTIME_EXCEPTION, message);\r
917                         }\r
918 \r
919                         (*env)->ReleaseStringUTFChars(env, statement, utfchars);\r
920 \r
921                         return result != NULL ? 0 : 1;\r
922                 }\r
923         }\r
924 }\r
925 \r
926 JNIEXPORT jstring JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
927         PyObject *module = (PyObject*)contextID;\r
928 \r
929         PyObject *pythonName = getPythonString(env, variableName);\r
930 \r
931         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
932         if (value == NULL) {\r
933                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
934                 return 0;\r
935         }\r
936 \r
937         if (!PyUnicode_Check(value)) {\r
938                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a string");\r
939                 return 0;\r
940         }\r
941 \r
942         {\r
943                 jstring result = pythonStringAsJavaString(env, value);\r
944                 return result;\r
945         }\r
946 }\r
947 \r
948 JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
949         PyObject *module = (PyObject*)contextID;\r
950 \r
951         PyObject *pythonName = getPythonString(env, variableName);\r
952 \r
953         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
954         if (value == NULL) {\r
955                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
956                 return 0;\r
957         }\r
958 \r
959         if (!PySequence_Check(value)) {\r
960                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
961                 return 0;\r
962         }\r
963 \r
964         {\r
965                 jobjectArray result = pythonSequenceAsStringArray(env, value);\r
966                 return result;\r
967         }\r
968 }\r
969 \r
970 JNIEXPORT jboolean JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonBooleanVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
971         PyObject *module = (PyObject*)contextID;\r
972 \r
973         PyObject *pythonName = getPythonString(env, variableName);\r
974 \r
975         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
976         if (value == NULL) {\r
977                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
978                 return 0;\r
979         }\r
980 \r
981         if (!PyBool_Check(value)) {\r
982                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a boolean");\r
983                 return 0;\r
984         }\r
985 \r
986         return value == Py_True;\r
987 }\r
988 \r
989 JNIEXPORT jbooleanArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonBooleanArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
990         PyObject *module = (PyObject*)contextID;\r
991 \r
992         PyObject *pythonName = getPythonString(env, variableName);\r
993 \r
994         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
995         if (value == NULL) {\r
996                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
997                 return 0;\r
998         }\r
999 \r
1000         if (!PySequence_Check(value)) {\r
1001                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
1002                 return 0;\r
1003         }\r
1004 \r
1005         {\r
1006                 jbooleanArray result = pythonSequenceAsBooleanArray(env, value);\r
1007                 return result;\r
1008         }\r
1009 }\r
1010 \r
1011 JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLongVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
1012         PyObject *module = (PyObject*)contextID;\r
1013 \r
1014         PyObject *pythonName = getPythonString(env, variableName);\r
1015 \r
1016         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
1017         if (value == NULL) {\r
1018                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
1019                 return 0;\r
1020         }\r
1021 \r
1022         if (!PyLong_Check(value)) {\r
1023                 throwException(env, RUNTIME_EXCEPTION, "Python variable not an integer");\r
1024                 return 0;\r
1025         }\r
1026 \r
1027         {\r
1028                 jlong result = PyLong_AsLongLong(value);\r
1029                 return result;\r
1030         }\r
1031 }\r
1032 \r
1033 JNIEXPORT jintArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
1034         PyObject *module = (PyObject*)contextID;\r
1035 \r
1036         PyObject *pythonName = getPythonString(env, variableName);\r
1037 \r
1038         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
1039         if (value == NULL) {\r
1040                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
1041                 return NULL;\r
1042         }\r
1043 \r
1044         if (!PySequence_Check(value)) {\r
1045                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
1046                 return NULL;\r
1047         }\r
1048 \r
1049         {\r
1050                 jintArray result = pythonSequenceAsIntegerArray(env, value);\r
1051                 return result;\r
1052         }\r
1053 }\r
1054 \r
1055 JNIEXPORT jlongArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLongArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
1056         PyObject *module = (PyObject*)contextID;\r
1057 \r
1058         PyObject *pythonName = getPythonString(env, variableName);\r
1059 \r
1060         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
1061         if (value == NULL) {\r
1062                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
1063                 return NULL;\r
1064         }\r
1065 \r
1066         if (!PySequence_Check(value)) {\r
1067                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
1068                 return NULL;\r
1069         }\r
1070 \r
1071         {\r
1072                 jlongArray result = pythonSequenceAsLongArray(env, value);\r
1073                 return result;\r
1074         }\r
1075 }\r
1076 \r
1077 JNIEXPORT jdouble JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
1078         PyObject *module = (PyObject*)contextID;\r
1079 \r
1080         PyObject *pythonName = getPythonString(env, variableName);\r
1081 \r
1082         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
1083         if (value == NULL) {\r
1084                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
1085                 return 0.0;\r
1086         }\r
1087 \r
1088         if (!PyFloat_Check(value)) {\r
1089                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a float");\r
1090                 return 0.0;\r
1091         }\r
1092 \r
1093         {\r
1094                 jdouble result = PyFloat_AsDouble(value);\r
1095                 return result;\r
1096         }\r
1097 }\r
1098 \r
1099 JNIEXPORT jdoubleArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
1100         PyObject *module = (PyObject*)contextID;\r
1101 \r
1102         PyObject *pythonName = getPythonString(env, variableName);\r
1103 \r
1104         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
1105         if (value == NULL) {\r
1106                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
1107                 return NULL;\r
1108         }\r
1109 \r
1110         if (!PySequence_Check(value)) {\r
1111                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
1112                 return NULL;\r
1113         }\r
1114 \r
1115         {\r
1116                 jdoubleArray result = pythonSequenceAsDoubleArray(env, value);\r
1117                 return result;\r
1118         }\r
1119 }\r
1120 \r
1121 JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
1122         PyObject *module = (PyObject*)contextID;\r
1123 \r
1124         if (!hasNumpy) {\r
1125                 throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed");\r
1126                 return NULL;\r
1127         }\r
1128 \r
1129         {\r
1130                 PyObject *pythonName = getPythonString(env, variableName);\r
1131 \r
1132                 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
1133                 if (value == NULL) {\r
1134                         throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
1135                         return NULL;\r
1136                 }\r
1137 \r
1138                 if (!PyArray_Check(value)) {\r
1139                         throwException(env, RUNTIME_EXCEPTION, "Python variable not an ndarray");\r
1140                         return NULL;\r
1141                 }\r
1142 \r
1143                 if (PyArray_TYPE((PyArrayObject*)value) != NPY_DOUBLE) {\r
1144                         throwException(env, RUNTIME_EXCEPTION, "Only ndarrays of type double are supported");\r
1145                         return NULL;\r
1146                 }\r
1147 \r
1148                 {\r
1149                         jobject result = pythonArrayAsNDArray(env, (PyArrayObject *)value);\r
1150                         return result;\r
1151                 }\r
1152         }\r
1153 }\r
1154 \r
1155 JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariantVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
1156         PyObject *module = (PyObject*)contextID;\r
1157 \r
1158         PyObject *pythonName = getPythonString(env, variableName);\r
1159 \r
1160         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
1161         if (value == NULL) {\r
1162                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
1163                 return NULL;\r
1164         }\r
1165 \r
1166         hasNumpy = _import_array() != -1;\r
1167 \r
1168         {\r
1169                 jobject result = pythonObjectAsObject(env, value);\r
1170                 return result;\r
1171         }\r
1172 }\r
1173 \r
1174 JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariableTypeImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
1175         PyObject *module = (PyObject*)contextID;\r
1176         PyObject *dict = PyModule_GetDict(module);\r
1177 \r
1178         PyObject *pythonName = getPythonString(env, variableName);\r
1179 \r
1180         if (!PyDict_Contains(dict, pythonName)) {\r
1181                 return 0;\r
1182         }\r
1183 \r
1184         {\r
1185                 PyObject *value = PyDict_GetItem(dict, pythonName);\r
1186 \r
1187                 jint result;\r
1188 \r
1189                 if (PyBool_Check(value))\r
1190                         result = 1;\r
1191                 else if (PyLong_Check(value))\r
1192                         result = 2;\r
1193                 else if (PyFloat_Check(value))\r
1194                         result = 3;\r
1195                 else if (PyUnicode_Check(value))\r
1196                         result = 4;\r
1197                 else if (PyByteArray_Check(value))\r
1198                         result = 5;\r
1199                 else if (PyDict_Check(value))\r
1200                         result = 6;\r
1201                 else if (hasNumpy && PyArray_Check(value))\r
1202                         result = 7;\r
1203                 else if (PySequence_Check(value))\r
1204                         result = 8;\r
1205                 else\r
1206                         result = -1;\r
1207 \r
1208                 return result;\r
1209         }\r
1210 }\r
1211 \r
1212 JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariableNamesImpl(JNIEnv *env, jobject thisObj, jlong contextID) {\r
1213         PyObject *module = (PyObject*)contextID;\r
1214         PyObject *dict = PyModule_GetDict(module);\r
1215 \r
1216         PyObject *keys = PyDict_Keys(dict);\r
1217         Py_ssize_t size = PyList_Size(keys);\r
1218 \r
1219         jobjectArray result = (*env)->NewObjectArray(env, (jsize)size, (*env)->FindClass(env, STRING_CLASS), NULL);\r
1220 \r
1221         Py_ssize_t i;\r
1222         for (i = 0; i < size; i++) {\r
1223                 jstring javaName = pythonStringAsJavaString(env, PyList_GetItem(keys, i));\r
1224                 (*env)->SetObjectArrayElement(env, result, (jint)i, javaName);\r
1225         }\r
1226 \r
1227         Py_XDECREF(keys);\r
1228 \r
1229         return result;\r
1230 }\r
1231 \r
1232 BOOL __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)\r
1233 //extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)\r
1234 {\r
1235     switch (fdwReason)\r
1236     {\r
1237         case DLL_PROCESS_ATTACH:\r
1238             // attach to process\r
1239             // return FALSE to fail DLL load\r
1240             break;\r
1241 \r
1242         case DLL_PROCESS_DETACH:\r
1243             // detach from process\r
1244             break;\r
1245 \r
1246         case DLL_THREAD_ATTACH:\r
1247             // attach to thread\r
1248             break;\r
1249 \r
1250         case DLL_THREAD_DETACH:\r
1251             // detach from thread\r
1252             break;\r
1253     }\r
1254     return TRUE; // succesful\r
1255 }\r