]> gerrit.simantics Code Review - simantics/python.git/blobdiff - 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
diff --git a/org.simantics.pythonlink.win32.x86_64/src/sclpy.c b/org.simantics.pythonlink.win32.x86_64/src/sclpy.c
new file mode 100644 (file)
index 0000000..4f5da9b
--- /dev/null
@@ -0,0 +1,600 @@
+///////////////////////////////////////////////////////\r
+//                                                   //\r
+//   VTT Technical Research Centre of Finland LTD    //\r
+//   For internal use only. Do not redistribute.     //\r
+//                                                   //\r
+//   Authors:                                        //\r
+//       Antton Tapani    ext-antton.tapani@vtt.fi   //\r
+//                                                   //\r
+//   Last modified by Antton Tapani    9.2016        //\r
+//                                                   //\r
+///////////////////////////////////////////////////////\r
+\r
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\r
+#ifdef _DEBUG\r
+       #undef _DEBUG\r
+       #include <Python.h>  //header for system python import; add include paths\r
+       #include <numpy/arrayobject.h>\r
+       #define _DEBUG 1\r
+#else\r
+       #include <Python.h>  //header for system python import; add include paths\r
+       #include <numpy/arrayobject.h>\r
+#endif\r
+\r
+#include "sclpy.h"\r
+\r
+#include <jni.h> //java connection header\r
+\r
+#include <windows.h>\r
+\r
+#define JAVA_MAXINT (0x7fffffff)\r
+\r
+#define RUNTIME_EXCEPTION "java/lang/RuntimeException"\r
+#define ILLEGAL_ARGUMENT_EXCEPTION "java/lang/IllegalArgumentException"\r
+#define STRING_CLASS "java/lang/String"\r
+\r
+#define PACKAGE_PREFIX "org/simantics/pythonlink/"\r
+\r
+#define NDARRAY_CLASS (PACKAGE_PREFIX "NDArray")\r
+\r
+jint throwException( JNIEnv *env, char *className, char *message )\r
+{\r
+    jclass exClass = (*env)->FindClass( env, className);\r
+    if (exClass == NULL) {\r
+        return 0;\r
+    }\r
+\r
+    return (*env)->ThrowNew( env, exClass, message );\r
+}\r
+\r
+jint throwIllegalArgumentException( JNIEnv *env, char *message ) {\r
+       return throwException( env, ILLEGAL_ARGUMENT_EXCEPTION, message );\r
+}\r
+\r
+int moduleCount = 0;\r
+\r
+JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContextImpl(JNIEnv *env, jobject thisObj) {\r
+       char name[16];\r
+       sprintf(name, "SCL_%d", ++moduleCount);\r
+\r
+       {\r
+               PyObject *module = PyModule_New(name);\r
+               PyObject *main = PyImport_AddModule("__main__");\r
+\r
+               PyDict_Merge(PyModule_GetDict(module), PyModule_GetDict(main), 0);\r
+               return (jlong)module;\r
+       }\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_deleteContextImpl(JNIEnv *env, jobject thisObj, jlong contextID) {\r
+       PyObject *module = (PyObject*)contextID;\r
+       Py_XDECREF(module);\r
+}\r
+\r
+PyObject *getPythonString(JNIEnv *env, jstring string) {\r
+       jsize len = (*env)->GetStringLength(env, string);\r
+       const jchar *chars = (*env)->GetStringChars(env, string, NULL);\r
+\r
+       PyObject *value = PyUnicode_DecodeUTF16((char*)chars, 2*len, NULL, NULL);\r
+\r
+       (*env)->ReleaseStringChars(env, string, chars);\r
+       return value;\r
+}\r
+\r
+PyObject *getPythonStringList(JNIEnv *env, jobjectArray value) {\r
+       jsize nitems = (*env)->GetArrayLength(env, value);\r
+       jint *values = (*env)->GetIntArrayElements(env, value, NULL);\r
+       jclass stringClass = (*env)->FindClass(env, STRING_CLASS);\r
+       jint i;\r
+\r
+       PyObject *result = PyList_New(nitems);\r
+       for (i = 0; i < nitems; i++) {\r
+               jobject item = (*env)->GetObjectArrayElement(env, value, i);\r
+               if (item != NULL && (*env)->IsInstanceOf(env, item, stringClass)) {\r
+                       PyList_SetItem(result, i, getPythonString(env, (jstring)item));\r
+               }\r
+               else {\r
+                       PyList_SetItem(result, i, Py_None);\r
+               }\r
+       }\r
+\r
+       (*env)->ReleaseIntArrayElements(env, value, values, JNI_ABORT);\r
+       return result;\r
+}\r
+\r
+PyObject *getPythonIntegerList(JNIEnv *env, jintArray value) {\r
+       jsize nitems = (*env)->GetArrayLength(env, value);\r
+       jint *values = (*env)->GetIntArrayElements(env, value, NULL);\r
+       jint i;\r
+\r
+       PyObject *result = PyList_New(nitems);\r
+       for (i = 0; i < nitems; i++) {\r
+               PyList_SetItem(result, i, PyLong_FromLong(values[i]));\r
+       }\r
+\r
+       (*env)->ReleaseIntArrayElements(env, value, values, JNI_ABORT);\r
+       return result;\r
+}\r
+\r
+PyObject *getPythonDoubleList(JNIEnv *env, jdoubleArray value) {\r
+       jsize nitems = (*env)->GetArrayLength(env, value);\r
+       double *values = (*env)->GetDoubleArrayElements(env, value, NULL);\r
+       jint i;\r
+\r
+       PyObject *result = PyList_New(nitems);\r
+       for (i = 0; i < nitems; i++) {\r
+               PyList_SetItem(result, i, PyFloat_FromDouble(values[i]));\r
+       }\r
+\r
+       (*env)->ReleaseDoubleArrayElements(env, value, values, JNI_ABORT);\r
+       return result;\r
+}\r
+\r
+PyObject *getPythonNDArray(JNIEnv *env, jobject value) {\r
+       jclass ndarrayClass = (*env)->FindClass(env, NDARRAY_CLASS);\r
+       jmethodID dimsMethod = (*env)->GetMethodID(env, ndarrayClass, "dims", "()[I");\r
+       jmethodID getValuesMethod = (*env)->GetMethodID(env, ndarrayClass, "getValues", "()[D");\r
+\r
+       jintArray jdims = (*env)->CallObjectMethod(env, value, dimsMethod);\r
+       jsize ndims = (*env)->GetArrayLength(env, jdims);\r
+       jint *dims = (*env)->GetIntArrayElements(env, jdims, NULL);\r
+\r
+       jdoubleArray jvalues = (*env)->CallObjectMethod(env, value, getValuesMethod);\r
+       jsize len = (*env)->GetArrayLength(env, jvalues);\r
+       jdouble *values = (*env)->GetDoubleArrayElements(env, jvalues, NULL);\r
+\r
+       npy_intp *pyDims = (npy_intp*)malloc(ndims * sizeof(npy_intp));\r
+\r
+       jint i, nelem = ndims > 0 ? 1 : 0;\r
+       for (i = 0; i < ndims; i++) {\r
+               nelem *= dims[i];\r
+               pyDims[i] = dims[i];\r
+       }\r
+\r
+       len = min(len, nelem);\r
+\r
+       {\r
+               PyObject *array = PyArray_EMPTY(ndims, pyDims, NPY_DOUBLE, 0);\r
+               double *data = (double *)PyArray_DATA((PyArrayObject*)array);\r
+\r
+               memcpy(data, values, len * sizeof(double));\r
+\r
+               free(pyDims);\r
+\r
+               (*env)->ReleaseDoubleArrayElements(env, jvalues, values, JNI_ABORT);\r
+               (*env)->ReleaseIntArrayElements(env, jdims, dims, JNI_ABORT);\r
+\r
+               return array;\r
+       }\r
+}\r
+\r
+void setPythonVariable(PyObject *module, PyObject *name, PyObject *value) {\r
+       if (name && value) {\r
+               PyDict_SetItem(PyModule_GetDict(module), name, value);\r
+       }\r
+\r
+       Py_XDECREF(name);\r
+       Py_XDECREF(value);\r
+}\r
+\r
+jstring pythonStringAsJavaString(JNIEnv *env, PyObject *string) {\r
+       PyObject *utf16Value = PyUnicode_AsUTF16String(string);\r
+       Py_ssize_t len = PyBytes_Size(utf16Value) / 2;\r
+       char *bytes = PyBytes_AsString(utf16Value);\r
+\r
+       // Create Java string, skipping the byte order mark in the beginning\r
+       jstring result = (*env)->NewString(env, (jchar *)bytes + 1, (jsize)min(len, JAVA_MAXINT) - 1);\r
+\r
+       Py_XDECREF(utf16Value);\r
+\r
+       return result;\r
+}\r
+\r
+jobjectArray pythonStringListAsJavaArray(JNIEnv *env, PyObject *list) {\r
+       Py_ssize_t len = PyList_Size(list);\r
+       jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
+       jobjectArray array = (*env)->NewObjectArray(env, jlen, (*env)->FindClass(env, STRING_CLASS), NULL);\r
+\r
+       jint i;\r
+\r
+       for (i = 0; i < jlen; i++) {\r
+               PyObject *item = PyList_GetItem(list, i);\r
+               if (PyUnicode_Check(item)) {\r
+                       jstring value = pythonStringAsJavaString(env, item);\r
+                       (*env)->SetObjectArrayElement(env, array, i, value);\r
+               }\r
+               else {\r
+                       throwException(env, RUNTIME_EXCEPTION, "List item not a string");\r
+                       return NULL;\r
+               }\r
+       }\r
+\r
+       return array;\r
+}\r
+\r
+jdoubleArray pythonListAsDoubleArray(JNIEnv *env, PyObject *list) {\r
+       Py_ssize_t len = PyList_Size(list);\r
+       jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
+       jdoubleArray array = (*env)->NewDoubleArray(env, jlen);\r
+\r
+       jint i;\r
+\r
+       for (i = 0; i < jlen; i++) {\r
+               PyObject *item = PyList_GetItem(list, i);\r
+               if (PyFloat_Check(item)) {\r
+                       double value = PyFloat_AsDouble(item);\r
+                       (*env)->SetDoubleArrayRegion(env, array, i, 1, &value);\r
+               }\r
+               else {\r
+                       throwException(env, RUNTIME_EXCEPTION, "List item not a floating point value");\r
+                       return NULL;\r
+               }\r
+       }\r
+\r
+       return array;\r
+}\r
+\r
+npy_intp nContiguous(int d, int nd, npy_intp *strides, npy_intp *dims, npy_intp *ncont) {\r
+       if (d == nd) {\r
+               ncont[d] = 1;\r
+               return 1;\r
+       }\r
+       else {\r
+               npy_intp n = nContiguous(d+1, nd, strides, dims, ncont);\r
+               ncont[d] = n > 0 && strides[d] == sizeof(double) * n ? dims[d] * n : 0;\r
+               return ncont[d];\r
+       }\r
+}\r
+\r
+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
+       if (ncont[d] > 0) {\r
+               (*env)->SetDoubleArrayRegion(env, array, (jint)*offset, (jint)ncont[d], data);\r
+               *offset += ncont[d];\r
+       }\r
+       else {\r
+               int i;\r
+               for (i = 0; i < dims[d]; i++) {\r
+                       copyDoubleArrayValues(env, array, (double*)((char*)data + strides[d] * i), offset, d+1, nd, strides, dims, ncont);\r
+               }\r
+       }\r
+}\r
+\r
+jobject pythonArrayAsNDArray(JNIEnv *env, PyArrayObject *array) {\r
+       jclass ndarrayClass = (*env)->FindClass(env, NDARRAY_CLASS);\r
+       jmethodID constructor = (*env)->GetMethodID(env, ndarrayClass, "<init>", "([I[D)V");\r
+\r
+       int ndims = PyArray_NDIM(array);\r
+       npy_intp *dims = PyArray_DIMS(array);\r
+\r
+       npy_intp len = PyArray_Size((PyObject*)array);\r
+       double *values = (double*)PyArray_DATA(array);\r
+\r
+       jboolean isFortran = PyArray_ISFORTRAN(array) != 0;\r
+\r
+       int i;\r
+\r
+       if (len > JAVA_MAXINT) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Array too large");\r
+               return NULL;\r
+       }\r
+\r
+       {\r
+               jintArray jdims = (*env)->NewIntArray(env, ndims);\r
+               jdoubleArray jvalues = (*env)->NewDoubleArray(env, (jsize)len);\r
+\r
+               for (i = 0; i < ndims; i++) {\r
+                       jint dim = (jint)dims[i];\r
+                       (*env)->SetIntArrayRegion(env, jdims, i, 1, &dim);\r
+               }\r
+\r
+               if (PyArray_IS_C_CONTIGUOUS(array)) {\r
+                       (*env)->SetDoubleArrayRegion(env, jvalues, 0, (jsize)len, values);\r
+               }\r
+               else {\r
+                       npy_intp offset = 0;\r
+                       npy_intp *strides = PyArray_STRIDES(array);\r
+                       npy_intp *ncont = (npy_intp*)malloc((ndims + 1) * sizeof(npy_intp));\r
+                       nContiguous(0, ndims, strides, dims, ncont);\r
+                       copyDoubleArrayValues(env, jvalues, values, &offset, 0, ndims, strides, dims, ncont);\r
+                       free(ncont);\r
+               }\r
+\r
+               return (*env)->NewObject(env, ndarrayClass, constructor, jdims, jvalues, isFortran);\r
+       }\r
+}\r
+\r
+jintArray pythonListAsIntegerArray(JNIEnv *env, PyObject *list) {\r
+       Py_ssize_t len = PyList_Size(list);\r
+       jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
+       jdoubleArray array = (*env)->NewIntArray(env, jlen);\r
+\r
+       jint i;\r
+\r
+       for (i = 0; i < jlen; i++) {\r
+               PyObject *item = PyList_GetItem(list, i);\r
+               if (PyLong_Check(item)) {\r
+                       jint value = PyLong_AsLong(item);\r
+                       (*env)->SetIntArrayRegion(env, array, i, 1, &value);\r
+               }\r
+               else {\r
+                       throwException(env, RUNTIME_EXCEPTION, "List item not an integer");\r
+                       return NULL;\r
+               }\r
+       }\r
+\r
+       return array;\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonIntegerVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jint value) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+       PyObject *val = PyLong_FromLong(value);\r
+\r
+       setPythonVariable(module, pythonName, val);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jintArray value) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+       PyObject *val = getPythonIntegerList(env, value);\r
+\r
+       setPythonVariable(module, pythonName, val);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdouble value) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+       PyObject *val = PyFloat_FromDouble(value);\r
+\r
+       setPythonVariable(module, pythonName, val);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdoubleArray value) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+       PyObject *val = getPythonDoubleList(env, value);\r
+\r
+       setPythonVariable(module, pythonName, val);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jstring value) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+       PyObject *val = getPythonString(env, value);\r
+\r
+       setPythonVariable(module, pythonName, val);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobjectArray value) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+       PyObject *val = getPythonStringList(env, value);\r
+\r
+       setPythonVariable(module, pythonName, val);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       if (_import_array() < 0) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed");\r
+               return;\r
+       }\r
+\r
+       {\r
+               PyObject *pythonName = getPythonString(env, variableName);\r
+               PyObject *val = getPythonNDArray(env, value);\r
+\r
+               setPythonVariable(module, pythonName, val);\r
+       }\r
+}\r
+\r
+JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePythonStatementImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring statement) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       const char *utfchars = (*env)->GetStringUTFChars(env, statement, NULL);\r
+\r
+       PyErr_Clear();\r
+       {\r
+               PyObject *globals;\r
+\r
+               globals = PyModule_GetDict(module);\r
+\r
+               {\r
+                       PyObject *result = PyRun_String(utfchars, Py_file_input, globals, globals);\r
+\r
+                       PyObject *exceptionType = PyErr_Occurred();\r
+                       if (exceptionType != NULL) {\r
+                               PyObject *exception, *stackTrace;\r
+                               char *message;\r
+                               PyErr_Fetch(&exceptionType, &exception, &stackTrace);\r
+                               message = PyUnicode_AsUTF8(exception);\r
+                               throwException(env, RUNTIME_EXCEPTION, message);\r
+                       }\r
+\r
+                       // Py_XDECREF(globals);\r
+\r
+                       (*env)->ReleaseStringUTFChars(env, statement, utfchars);\r
+\r
+                       return result != NULL ? 0 : 1;\r
+               }\r
+       }\r
+}\r
+\r
+JNIEXPORT jstring JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+\r
+       PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
+       if (value == NULL) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               return 0;\r
+       }\r
+\r
+       if (!PyUnicode_Check(value)) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not a string");\r
+               return 0;\r
+       }\r
+\r
+       return pythonStringAsJavaString(env, value);\r
+}\r
+\r
+JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+\r
+       PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
+       if (value == NULL) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               return 0;\r
+       }\r
+\r
+       if (!PyList_Check(value)) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not a list");\r
+               return 0;\r
+       }\r
+\r
+       return pythonStringListAsJavaArray(env, value);\r
+}\r
+\r
+JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonIntegerVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+\r
+       PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
+       if (value == NULL) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               return 0;\r
+       }\r
+\r
+       if (!PyLong_Check(value)) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not an integer");\r
+               return 0;\r
+       }\r
+\r
+       return PyLong_AsLong(value);\r
+}\r
+\r
+JNIEXPORT jintArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+\r
+       PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
+       if (value == NULL) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               return NULL;\r
+       }\r
+\r
+       if (!PyList_Check(value)) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not a list");\r
+               return NULL;\r
+       }\r
+\r
+       return pythonListAsIntegerArray(env, value);\r
+}\r
+\r
+JNIEXPORT jdouble JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+\r
+       PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
+       if (value == NULL) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               return 0.0;\r
+       }\r
+\r
+       if (!PyFloat_Check(value)) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not a float");\r
+               return 0.0;\r
+       }\r
+\r
+       return PyFloat_AsDouble(value);\r
+}\r
+\r
+JNIEXPORT jdoubleArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       PyObject *pythonName = getPythonString(env, variableName);\r
+\r
+       PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
+       if (value == NULL) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               return NULL;\r
+       }\r
+\r
+       if (!PyList_Check(value)) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Python variable not a list");\r
+               return NULL;\r
+       }\r
+\r
+       return pythonListAsDoubleArray(env, value);\r
+}\r
+\r
+JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
+       PyObject *module = (PyObject*)contextID;\r
+\r
+       if (_import_array() < 0) {\r
+               throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed");\r
+               return NULL;\r
+       }\r
+\r
+       {\r
+               PyObject *pythonName = getPythonString(env, variableName);\r
+\r
+               PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
+               if (value == NULL) {\r
+                       throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+                       return NULL;\r
+               }\r
+\r
+               if (!PyArray_Check(value)) {\r
+                       throwException(env, RUNTIME_EXCEPTION, "Python variable not an ndarray");\r
+                       return NULL;\r
+               }\r
+\r
+               if (PyArray_TYPE((PyArrayObject*)value) != NPY_DOUBLE) {\r
+                       throwException(env, RUNTIME_EXCEPTION, "Only ndarrays of type double are supported");\r
+                       return NULL;\r
+               }\r
+\r
+               return pythonArrayAsNDArray(env, (PyArrayObject *)value);\r
+       }\r
+}\r
+\r
+BOOL __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)\r
+//extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)\r
+{\r
+    switch (fdwReason)\r
+    {\r
+        case DLL_PROCESS_ATTACH:\r
+            // attach to process\r
+            // return FALSE to fail DLL load\r
+            Py_Initialize();\r
+            break;\r
+\r
+        case DLL_PROCESS_DETACH:\r
+            // detach from process\r
+               Py_Finalize();\r
+            break;\r
+\r
+        case DLL_THREAD_ATTACH:\r
+            // attach to thread\r
+            break;\r
+\r
+        case DLL_THREAD_DETACH:\r
+            // detach from thread\r
+            break;\r
+    }\r
+    return TRUE; // succesful\r
+}\r