]> gerrit.simantics Code Review - simantics/python.git/blob - org.simantics.pythonlink.win32.x86_64/src/sclpy.c
Added C source code for the DLL and a CDT project aspect for compiling it.
[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 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\r
14 #ifdef _DEBUG\r
15         #undef _DEBUG\r
16         #include <Python.h>  //header for system python import; add include paths\r
17         #include <numpy/arrayobject.h>\r
18         #define _DEBUG 1\r
19 #else\r
20         #include <Python.h>  //header for system python import; add include paths\r
21         #include <numpy/arrayobject.h>\r
22 #endif\r
23 \r
24 #include "sclpy.h"\r
25 \r
26 #include <jni.h> //java connection header\r
27 \r
28 #include <windows.h>\r
29 \r
30 #define JAVA_MAXINT (0x7fffffff)\r
31 \r
32 #define RUNTIME_EXCEPTION "java/lang/RuntimeException"\r
33 #define ILLEGAL_ARGUMENT_EXCEPTION "java/lang/IllegalArgumentException"\r
34 #define STRING_CLASS "java/lang/String"\r
35 \r
36 #define PACKAGE_PREFIX "org/simantics/pythonlink/"\r
37 \r
38 #define NDARRAY_CLASS (PACKAGE_PREFIX "NDArray")\r
39 \r
40 jint throwException( JNIEnv *env, char *className, char *message )\r
41 {\r
42     jclass exClass = (*env)->FindClass( env, className);\r
43     if (exClass == NULL) {\r
44         return 0;\r
45     }\r
46 \r
47     return (*env)->ThrowNew( env, exClass, message );\r
48 }\r
49 \r
50 jint throwIllegalArgumentException( JNIEnv *env, char *message ) {\r
51         return throwException( env, ILLEGAL_ARGUMENT_EXCEPTION, message );\r
52 }\r
53 \r
54 int moduleCount = 0;\r
55 \r
56 JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContextImpl(JNIEnv *env, jobject thisObj) {\r
57         char name[16];\r
58         sprintf(name, "SCL_%d", ++moduleCount);\r
59 \r
60         {\r
61                 PyObject *module = PyModule_New(name);\r
62                 PyObject *main = PyImport_AddModule("__main__");\r
63 \r
64                 PyDict_Merge(PyModule_GetDict(module), PyModule_GetDict(main), 0);\r
65                 return (jlong)module;\r
66         }\r
67 }\r
68 \r
69 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_deleteContextImpl(JNIEnv *env, jobject thisObj, jlong contextID) {\r
70         PyObject *module = (PyObject*)contextID;\r
71         Py_XDECREF(module);\r
72 }\r
73 \r
74 PyObject *getPythonString(JNIEnv *env, jstring string) {\r
75         jsize len = (*env)->GetStringLength(env, string);\r
76         const jchar *chars = (*env)->GetStringChars(env, string, NULL);\r
77 \r
78         PyObject *value = PyUnicode_DecodeUTF16((char*)chars, 2*len, NULL, NULL);\r
79 \r
80         (*env)->ReleaseStringChars(env, string, chars);\r
81         return value;\r
82 }\r
83 \r
84 PyObject *getPythonStringList(JNIEnv *env, jobjectArray value) {\r
85         jsize nitems = (*env)->GetArrayLength(env, value);\r
86         jint *values = (*env)->GetIntArrayElements(env, value, NULL);\r
87         jclass stringClass = (*env)->FindClass(env, STRING_CLASS);\r
88         jint i;\r
89 \r
90         PyObject *result = PyList_New(nitems);\r
91         for (i = 0; i < nitems; i++) {\r
92                 jobject item = (*env)->GetObjectArrayElement(env, value, i);\r
93                 if (item != NULL && (*env)->IsInstanceOf(env, item, stringClass)) {\r
94                         PyList_SetItem(result, i, getPythonString(env, (jstring)item));\r
95                 }\r
96                 else {\r
97                         PyList_SetItem(result, i, Py_None);\r
98                 }\r
99         }\r
100 \r
101         (*env)->ReleaseIntArrayElements(env, value, values, JNI_ABORT);\r
102         return result;\r
103 }\r
104 \r
105 PyObject *getPythonIntegerList(JNIEnv *env, jintArray value) {\r
106         jsize nitems = (*env)->GetArrayLength(env, value);\r
107         jint *values = (*env)->GetIntArrayElements(env, value, NULL);\r
108         jint i;\r
109 \r
110         PyObject *result = PyList_New(nitems);\r
111         for (i = 0; i < nitems; i++) {\r
112                 PyList_SetItem(result, i, PyLong_FromLong(values[i]));\r
113         }\r
114 \r
115         (*env)->ReleaseIntArrayElements(env, value, values, JNI_ABORT);\r
116         return result;\r
117 }\r
118 \r
119 PyObject *getPythonDoubleList(JNIEnv *env, jdoubleArray value) {\r
120         jsize nitems = (*env)->GetArrayLength(env, value);\r
121         double *values = (*env)->GetDoubleArrayElements(env, value, NULL);\r
122         jint i;\r
123 \r
124         PyObject *result = PyList_New(nitems);\r
125         for (i = 0; i < nitems; i++) {\r
126                 PyList_SetItem(result, i, PyFloat_FromDouble(values[i]));\r
127         }\r
128 \r
129         (*env)->ReleaseDoubleArrayElements(env, value, values, JNI_ABORT);\r
130         return result;\r
131 }\r
132 \r
133 PyObject *getPythonNDArray(JNIEnv *env, jobject value) {\r
134         jclass ndarrayClass = (*env)->FindClass(env, NDARRAY_CLASS);\r
135         jmethodID dimsMethod = (*env)->GetMethodID(env, ndarrayClass, "dims", "()[I");\r
136         jmethodID getValuesMethod = (*env)->GetMethodID(env, ndarrayClass, "getValues", "()[D");\r
137 \r
138         jintArray jdims = (*env)->CallObjectMethod(env, value, dimsMethod);\r
139         jsize ndims = (*env)->GetArrayLength(env, jdims);\r
140         jint *dims = (*env)->GetIntArrayElements(env, jdims, NULL);\r
141 \r
142         jdoubleArray jvalues = (*env)->CallObjectMethod(env, value, getValuesMethod);\r
143         jsize len = (*env)->GetArrayLength(env, jvalues);\r
144         jdouble *values = (*env)->GetDoubleArrayElements(env, jvalues, NULL);\r
145 \r
146         npy_intp *pyDims = (npy_intp*)malloc(ndims * sizeof(npy_intp));\r
147 \r
148         jint i, nelem = ndims > 0 ? 1 : 0;\r
149         for (i = 0; i < ndims; i++) {\r
150                 nelem *= dims[i];\r
151                 pyDims[i] = dims[i];\r
152         }\r
153 \r
154         len = min(len, nelem);\r
155 \r
156         {\r
157                 PyObject *array = PyArray_EMPTY(ndims, pyDims, NPY_DOUBLE, 0);\r
158                 double *data = (double *)PyArray_DATA((PyArrayObject*)array);\r
159 \r
160                 memcpy(data, values, len * sizeof(double));\r
161 \r
162                 free(pyDims);\r
163 \r
164                 (*env)->ReleaseDoubleArrayElements(env, jvalues, values, JNI_ABORT);\r
165                 (*env)->ReleaseIntArrayElements(env, jdims, dims, JNI_ABORT);\r
166 \r
167                 return array;\r
168         }\r
169 }\r
170 \r
171 void setPythonVariable(PyObject *module, PyObject *name, PyObject *value) {\r
172         if (name && value) {\r
173                 PyDict_SetItem(PyModule_GetDict(module), name, value);\r
174         }\r
175 \r
176         Py_XDECREF(name);\r
177         Py_XDECREF(value);\r
178 }\r
179 \r
180 jstring pythonStringAsJavaString(JNIEnv *env, PyObject *string) {\r
181         PyObject *utf16Value = PyUnicode_AsUTF16String(string);\r
182         Py_ssize_t len = PyBytes_Size(utf16Value) / 2;\r
183         char *bytes = PyBytes_AsString(utf16Value);\r
184 \r
185         // Create Java string, skipping the byte order mark in the beginning\r
186         jstring result = (*env)->NewString(env, (jchar *)bytes + 1, (jsize)min(len, JAVA_MAXINT) - 1);\r
187 \r
188         Py_XDECREF(utf16Value);\r
189 \r
190         return result;\r
191 }\r
192 \r
193 jobjectArray pythonStringListAsJavaArray(JNIEnv *env, PyObject *list) {\r
194         Py_ssize_t len = PyList_Size(list);\r
195         jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
196         jobjectArray array = (*env)->NewObjectArray(env, jlen, (*env)->FindClass(env, STRING_CLASS), NULL);\r
197 \r
198         jint i;\r
199 \r
200         for (i = 0; i < jlen; i++) {\r
201                 PyObject *item = PyList_GetItem(list, i);\r
202                 if (PyUnicode_Check(item)) {\r
203                         jstring value = pythonStringAsJavaString(env, item);\r
204                         (*env)->SetObjectArrayElement(env, array, i, value);\r
205                 }\r
206                 else {\r
207                         throwException(env, RUNTIME_EXCEPTION, "List item not a string");\r
208                         return NULL;\r
209                 }\r
210         }\r
211 \r
212         return array;\r
213 }\r
214 \r
215 jdoubleArray pythonListAsDoubleArray(JNIEnv *env, PyObject *list) {\r
216         Py_ssize_t len = PyList_Size(list);\r
217         jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
218         jdoubleArray array = (*env)->NewDoubleArray(env, jlen);\r
219 \r
220         jint i;\r
221 \r
222         for (i = 0; i < jlen; i++) {\r
223                 PyObject *item = PyList_GetItem(list, i);\r
224                 if (PyFloat_Check(item)) {\r
225                         double value = PyFloat_AsDouble(item);\r
226                         (*env)->SetDoubleArrayRegion(env, array, i, 1, &value);\r
227                 }\r
228                 else {\r
229                         throwException(env, RUNTIME_EXCEPTION, "List item not a floating point value");\r
230                         return NULL;\r
231                 }\r
232         }\r
233 \r
234         return array;\r
235 }\r
236 \r
237 npy_intp nContiguous(int d, int nd, npy_intp *strides, npy_intp *dims, npy_intp *ncont) {\r
238         if (d == nd) {\r
239                 ncont[d] = 1;\r
240                 return 1;\r
241         }\r
242         else {\r
243                 npy_intp n = nContiguous(d+1, nd, strides, dims, ncont);\r
244                 ncont[d] = n > 0 && strides[d] == sizeof(double) * n ? dims[d] * n : 0;\r
245                 return ncont[d];\r
246         }\r
247 }\r
248 \r
249 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
250         if (ncont[d] > 0) {\r
251                 (*env)->SetDoubleArrayRegion(env, array, (jint)*offset, (jint)ncont[d], data);\r
252                 *offset += ncont[d];\r
253         }\r
254         else {\r
255                 int i;\r
256                 for (i = 0; i < dims[d]; i++) {\r
257                         copyDoubleArrayValues(env, array, (double*)((char*)data + strides[d] * i), offset, d+1, nd, strides, dims, ncont);\r
258                 }\r
259         }\r
260 }\r
261 \r
262 jobject pythonArrayAsNDArray(JNIEnv *env, PyArrayObject *array) {\r
263         jclass ndarrayClass = (*env)->FindClass(env, NDARRAY_CLASS);\r
264         jmethodID constructor = (*env)->GetMethodID(env, ndarrayClass, "<init>", "([I[D)V");\r
265 \r
266         int ndims = PyArray_NDIM(array);\r
267         npy_intp *dims = PyArray_DIMS(array);\r
268 \r
269         npy_intp len = PyArray_Size((PyObject*)array);\r
270         double *values = (double*)PyArray_DATA(array);\r
271 \r
272         jboolean isFortran = PyArray_ISFORTRAN(array) != 0;\r
273 \r
274         int i;\r
275 \r
276         if (len > JAVA_MAXINT) {\r
277                 throwException(env, RUNTIME_EXCEPTION, "Array too large");\r
278                 return NULL;\r
279         }\r
280 \r
281         {\r
282                 jintArray jdims = (*env)->NewIntArray(env, ndims);\r
283                 jdoubleArray jvalues = (*env)->NewDoubleArray(env, (jsize)len);\r
284 \r
285                 for (i = 0; i < ndims; i++) {\r
286                         jint dim = (jint)dims[i];\r
287                         (*env)->SetIntArrayRegion(env, jdims, i, 1, &dim);\r
288                 }\r
289 \r
290                 if (PyArray_IS_C_CONTIGUOUS(array)) {\r
291                         (*env)->SetDoubleArrayRegion(env, jvalues, 0, (jsize)len, values);\r
292                 }\r
293                 else {\r
294                         npy_intp offset = 0;\r
295                         npy_intp *strides = PyArray_STRIDES(array);\r
296                         npy_intp *ncont = (npy_intp*)malloc((ndims + 1) * sizeof(npy_intp));\r
297                         nContiguous(0, ndims, strides, dims, ncont);\r
298                         copyDoubleArrayValues(env, jvalues, values, &offset, 0, ndims, strides, dims, ncont);\r
299                         free(ncont);\r
300                 }\r
301 \r
302                 return (*env)->NewObject(env, ndarrayClass, constructor, jdims, jvalues, isFortran);\r
303         }\r
304 }\r
305 \r
306 jintArray pythonListAsIntegerArray(JNIEnv *env, PyObject *list) {\r
307         Py_ssize_t len = PyList_Size(list);\r
308         jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
309         jdoubleArray array = (*env)->NewIntArray(env, jlen);\r
310 \r
311         jint i;\r
312 \r
313         for (i = 0; i < jlen; i++) {\r
314                 PyObject *item = PyList_GetItem(list, i);\r
315                 if (PyLong_Check(item)) {\r
316                         jint value = PyLong_AsLong(item);\r
317                         (*env)->SetIntArrayRegion(env, array, i, 1, &value);\r
318                 }\r
319                 else {\r
320                         throwException(env, RUNTIME_EXCEPTION, "List item not an integer");\r
321                         return NULL;\r
322                 }\r
323         }\r
324 \r
325         return array;\r
326 }\r
327 \r
328 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonIntegerVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jint value) {\r
329         PyObject *module = (PyObject*)contextID;\r
330 \r
331         PyObject *pythonName = getPythonString(env, variableName);\r
332         PyObject *val = PyLong_FromLong(value);\r
333 \r
334         setPythonVariable(module, pythonName, val);\r
335 }\r
336 \r
337 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jintArray value) {\r
338         PyObject *module = (PyObject*)contextID;\r
339 \r
340         PyObject *pythonName = getPythonString(env, variableName);\r
341         PyObject *val = getPythonIntegerList(env, value);\r
342 \r
343         setPythonVariable(module, pythonName, val);\r
344 }\r
345 \r
346 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdouble value) {\r
347         PyObject *module = (PyObject*)contextID;\r
348 \r
349         PyObject *pythonName = getPythonString(env, variableName);\r
350         PyObject *val = PyFloat_FromDouble(value);\r
351 \r
352         setPythonVariable(module, pythonName, val);\r
353 }\r
354 \r
355 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdoubleArray value) {\r
356         PyObject *module = (PyObject*)contextID;\r
357 \r
358         PyObject *pythonName = getPythonString(env, variableName);\r
359         PyObject *val = getPythonDoubleList(env, value);\r
360 \r
361         setPythonVariable(module, pythonName, val);\r
362 }\r
363 \r
364 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jstring value) {\r
365         PyObject *module = (PyObject*)contextID;\r
366 \r
367         PyObject *pythonName = getPythonString(env, variableName);\r
368         PyObject *val = getPythonString(env, value);\r
369 \r
370         setPythonVariable(module, pythonName, val);\r
371 }\r
372 \r
373 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobjectArray value) {\r
374         PyObject *module = (PyObject*)contextID;\r
375 \r
376         PyObject *pythonName = getPythonString(env, variableName);\r
377         PyObject *val = getPythonStringList(env, value);\r
378 \r
379         setPythonVariable(module, pythonName, val);\r
380 }\r
381 \r
382 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value) {\r
383         PyObject *module = (PyObject*)contextID;\r
384 \r
385         if (_import_array() < 0) {\r
386                 throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed");\r
387                 return;\r
388         }\r
389 \r
390         {\r
391                 PyObject *pythonName = getPythonString(env, variableName);\r
392                 PyObject *val = getPythonNDArray(env, value);\r
393 \r
394                 setPythonVariable(module, pythonName, val);\r
395         }\r
396 }\r
397 \r
398 JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePythonStatementImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring statement) {\r
399         PyObject *module = (PyObject*)contextID;\r
400 \r
401         const char *utfchars = (*env)->GetStringUTFChars(env, statement, NULL);\r
402 \r
403         PyErr_Clear();\r
404         {\r
405                 PyObject *globals;\r
406 \r
407                 globals = PyModule_GetDict(module);\r
408 \r
409                 {\r
410                         PyObject *result = PyRun_String(utfchars, Py_file_input, globals, globals);\r
411 \r
412                         PyObject *exceptionType = PyErr_Occurred();\r
413                         if (exceptionType != NULL) {\r
414                                 PyObject *exception, *stackTrace;\r
415                                 char *message;\r
416                                 PyErr_Fetch(&exceptionType, &exception, &stackTrace);\r
417                                 message = PyUnicode_AsUTF8(exception);\r
418                                 throwException(env, RUNTIME_EXCEPTION, message);\r
419                         }\r
420 \r
421                         // Py_XDECREF(globals);\r
422 \r
423                         (*env)->ReleaseStringUTFChars(env, statement, utfchars);\r
424 \r
425                         return result != NULL ? 0 : 1;\r
426                 }\r
427         }\r
428 }\r
429 \r
430 JNIEXPORT jstring JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
431         PyObject *module = (PyObject*)contextID;\r
432 \r
433         PyObject *pythonName = getPythonString(env, variableName);\r
434 \r
435         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
436         if (value == NULL) {\r
437                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
438                 return 0;\r
439         }\r
440 \r
441         if (!PyUnicode_Check(value)) {\r
442                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a string");\r
443                 return 0;\r
444         }\r
445 \r
446         return pythonStringAsJavaString(env, value);\r
447 }\r
448 \r
449 JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
450         PyObject *module = (PyObject*)contextID;\r
451 \r
452         PyObject *pythonName = getPythonString(env, variableName);\r
453 \r
454         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
455         if (value == NULL) {\r
456                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
457                 return 0;\r
458         }\r
459 \r
460         if (!PyList_Check(value)) {\r
461                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a list");\r
462                 return 0;\r
463         }\r
464 \r
465         return pythonStringListAsJavaArray(env, value);\r
466 }\r
467 \r
468 JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonIntegerVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
469         PyObject *module = (PyObject*)contextID;\r
470 \r
471         PyObject *pythonName = getPythonString(env, variableName);\r
472 \r
473         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
474         if (value == NULL) {\r
475                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
476                 return 0;\r
477         }\r
478 \r
479         if (!PyLong_Check(value)) {\r
480                 throwException(env, RUNTIME_EXCEPTION, "Python variable not an integer");\r
481                 return 0;\r
482         }\r
483 \r
484         return PyLong_AsLong(value);\r
485 }\r
486 \r
487 JNIEXPORT jintArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
488         PyObject *module = (PyObject*)contextID;\r
489 \r
490         PyObject *pythonName = getPythonString(env, variableName);\r
491 \r
492         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
493         if (value == NULL) {\r
494                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
495                 return NULL;\r
496         }\r
497 \r
498         if (!PyList_Check(value)) {\r
499                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a list");\r
500                 return NULL;\r
501         }\r
502 \r
503         return pythonListAsIntegerArray(env, value);\r
504 }\r
505 \r
506 JNIEXPORT jdouble JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
507         PyObject *module = (PyObject*)contextID;\r
508 \r
509         PyObject *pythonName = getPythonString(env, variableName);\r
510 \r
511         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
512         if (value == NULL) {\r
513                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
514                 return 0.0;\r
515         }\r
516 \r
517         if (!PyFloat_Check(value)) {\r
518                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a float");\r
519                 return 0.0;\r
520         }\r
521 \r
522         return PyFloat_AsDouble(value);\r
523 }\r
524 \r
525 JNIEXPORT jdoubleArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
526         PyObject *module = (PyObject*)contextID;\r
527 \r
528         PyObject *pythonName = getPythonString(env, variableName);\r
529 \r
530         PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
531         if (value == NULL) {\r
532                 throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
533                 return NULL;\r
534         }\r
535 \r
536         if (!PyList_Check(value)) {\r
537                 throwException(env, RUNTIME_EXCEPTION, "Python variable not a list");\r
538                 return NULL;\r
539         }\r
540 \r
541         return pythonListAsDoubleArray(env, value);\r
542 }\r
543 \r
544 JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
545         PyObject *module = (PyObject*)contextID;\r
546 \r
547         if (_import_array() < 0) {\r
548                 throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed");\r
549                 return NULL;\r
550         }\r
551 \r
552         {\r
553                 PyObject *pythonName = getPythonString(env, variableName);\r
554 \r
555                 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
556                 if (value == NULL) {\r
557                         throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
558                         return NULL;\r
559                 }\r
560 \r
561                 if (!PyArray_Check(value)) {\r
562                         throwException(env, RUNTIME_EXCEPTION, "Python variable not an ndarray");\r
563                         return NULL;\r
564                 }\r
565 \r
566                 if (PyArray_TYPE((PyArrayObject*)value) != NPY_DOUBLE) {\r
567                         throwException(env, RUNTIME_EXCEPTION, "Only ndarrays of type double are supported");\r
568                         return NULL;\r
569                 }\r
570 \r
571                 return pythonArrayAsNDArray(env, (PyArrayObject *)value);\r
572         }\r
573 }\r
574 \r
575 BOOL __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)\r
576 //extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)\r
577 {\r
578     switch (fdwReason)\r
579     {\r
580         case DLL_PROCESS_ATTACH:\r
581             // attach to process\r
582             // return FALSE to fail DLL load\r
583             Py_Initialize();\r
584             break;\r
585 \r
586         case DLL_PROCESS_DETACH:\r
587             // detach from process\r
588                 Py_Finalize();\r
589             break;\r
590 \r
591         case DLL_THREAD_ATTACH:\r
592             // attach to thread\r
593             break;\r
594 \r
595         case DLL_THREAD_DETACH:\r
596             // detach from thread\r
597             break;\r
598     }\r
599     return TRUE; // succesful\r
600 }\r