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