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