-///////////////////////////////////////////////////////\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
-#include "sclpy.h"\r
-\r
-#include <windows.h>\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 throwPythonException( JNIEnv *env, char *message ) {\r
- return throwException( env, PYTHON_EXCEPTION, 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
-int initCalled = 0;\r
-int hasNumpy = 0;\r
-\r
-JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContextImpl(JNIEnv *env, jobject thisObj) {\r
- char name[16];\r
-\r
- if (!initCalled) {\r
- Py_Initialize();\r
- initCalled = 1;\r
-\r
- hasNumpy = _import_array();\r
- hasNumpy = hasNumpy != -1;\r
- }\r
-\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
-\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 *getPythonBool(jboolean value) {\r
- if (value) {\r
- Py_RETURN_TRUE;\r
- }\r
- else {\r
- Py_RETURN_FALSE;\r
- }\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 *getPythonBooleanList(JNIEnv *env, jbooleanArray value) {\r
- jsize nitems = (*env)->GetArrayLength(env, value);\r
- jboolean *values = (*env)->GetBooleanArrayElements(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, getPythonBool(values[i]));\r
- }\r
-\r
- (*env)->ReleaseBooleanArrayElements(env, value, values, JNI_ABORT);\r
- return result;\r
-}\r
-\r
-PyObject *getPythonByteArray(JNIEnv *env, jbyteArray value) {\r
- jint len = (*env)->GetArrayLength(env, value);\r
- jbyte *values = (*env)->GetByteArrayElements(env, value, NULL);\r
-\r
- PyObject *result = PyByteArray_FromStringAndSize(values, len);\r
-\r
- (*env)->ReleaseByteArrayElements(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 *getPythonLongList(JNIEnv *env, jlongArray value) {\r
- jsize nitems = (*env)->GetArrayLength(env, value);\r
- jlong *values = (*env)->GetLongArrayElements(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_FromLongLong(values[i]));\r
- }\r
-\r
- (*env)->ReleaseLongArrayElements(env, value, values, JNI_ABORT);\r
- return result;\r
-}\r
-\r
-PyObject *getPythonFloatList(JNIEnv *env, jfloatArray value) {\r
- jsize nitems = (*env)->GetArrayLength(env, value);\r
- float *values = (*env)->GetFloatArrayElements(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((double)values[i]));\r
- }\r
-\r
- (*env)->ReleaseFloatArrayElements(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
-PyObject *getPythonBooleanObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, BOOLEANBINDING_CLASS);\r
- jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)Z");\r
-\r
- jboolean bvalue = (*env)->CallBooleanMethod(env, binding, getValueMethod, object);\r
- return getPythonBool(bvalue);\r
-}\r
-\r
-PyObject *getPythonByteObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, BYTEBINDING_CLASS);\r
- jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)B");\r
-\r
- jbyte v = (*env)->CallByteMethod(env, binding, getValueMethod, object);\r
- return PyLong_FromLong(v);\r
-}\r
-\r
-PyObject *getPythonIntegerObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, INTEGERBINDING_CLASS);\r
- jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)I");\r
-\r
- jint v = (*env)->CallIntMethod(env, binding, getValueMethod, object);\r
- return PyLong_FromLong(v);\r
-}\r
-\r
-PyObject *getPythonLongObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, LONGBINDING_CLASS);\r
- jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)J");\r
-\r
- jlong v = (*env)->CallLongMethod(env, binding, getValueMethod, object);\r
- return PyLong_FromLongLong(v);\r
-}\r
-\r
-PyObject *getPythonFloatObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, FLOATBINDING_CLASS);\r
- jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)F");\r
-\r
- jfloat v = (*env)->CallFloatMethod(env, binding, getValueMethod, object);\r
- return PyFloat_FromDouble(v);\r
-}\r
-\r
-PyObject *getPythonDoubleObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, DOUBLEBINDING_CLASS);\r
- jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)D");\r
-\r
- jdouble v = (*env)->CallDoubleMethod(env, binding, getValueMethod, object);\r
- return PyFloat_FromDouble(v);\r
-}\r
-\r
-PyObject *getPythonStringObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, STRINGBINDING_CLASS);\r
- jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue", "(L" OBJECT_CLASS ";)L" STRING_CLASS ";");\r
-\r
- jobject string = (*env)->CallObjectMethod(env, binding, getValueMethod, object);\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 *getPythonRecordObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, RECORDBINDING_CLASS);\r
- jmethodID typeMethod = (*env)->GetMethodID(env, bindingClass, "type", "()L" RECORDTYPE_CLASS ";");\r
- jmethodID getComponent = (*env)->GetMethodID(env, bindingClass, "getComponent", "(L" OBJECT_CLASS ";I)L" OBJECT_CLASS ";");\r
- jmethodID getComponentBinding = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "(I)L" BINDING_CLASS ";");\r
-\r
- jclass recordType = (*env)->FindClass(env, RECORDTYPE_CLASS);\r
- jmethodID getTypeComponent = (*env)->GetMethodID(env, recordType, "getComponent", "(I)L" COMPONENT_CLASS ";");\r
- jmethodID getComponentCount = (*env)->GetMethodID(env, recordType, "getComponentCount", "()I");\r
-\r
- jclass componentClass = (*env)->FindClass(env, COMPONENT_CLASS);\r
- jfieldID nameField = (*env)->GetFieldID(env, componentClass, "name", "L" STRING_CLASS ";");\r
-\r
- jobject type = (*env)->CallObjectMethod(env, binding, typeMethod);\r
- jint n = (*env)->CallIntMethod(env, type, getComponentCount);\r
- jint i;\r
-\r
- PyObject *result = PyDict_New();\r
- for (i = 0; i < n; i++) {\r
- jobject recordTypeComponent = (*env)->CallObjectMethod(env, type, getComponent, i);\r
- jstring fieldName = (jstring)(*env)->GetObjectField(env, recordTypeComponent, nameField);\r
- jobject componentObject = (*env)->CallObjectMethod(env, binding, getComponent, object, i);\r
- jobject componentBinding = (*env)->CallObjectMethod(env, binding, getComponentBinding, i);\r
-\r
- PyObject *item = getPythonObject(env, componentObject, componentBinding);\r
- PyDict_SetItem(result, getPythonString(env, fieldName), item);\r
- }\r
-\r
- return result;\r
-}\r
-\r
-PyObject *getPythonArrayObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, ARRAYBINDING_CLASS);\r
- jmethodID componentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "()L" BINDING_CLASS ";");\r
- jmethodID sizeMethod = (*env)->GetMethodID(env, bindingClass, "size", "(L" OBJECT_CLASS ";)I");\r
- jmethodID getMethod = (*env)->GetMethodID(env, bindingClass, "get", "(L" OBJECT_CLASS ";I)L" OBJECT_CLASS ";");\r
-\r
- jobject componentBinding = (*env)->CallObjectMethod(env, binding, componentBindingMethod);\r
-\r
- jint size = (*env)->CallIntMethod(env, binding, sizeMethod, object);\r
-\r
- PyObject *result = PyList_New(size);\r
-\r
- jint i;\r
- for (i = 0; i < size; i++) {\r
- jobject item = (*env)->CallObjectMethod(env, binding, getMethod, object, i);\r
- if (item != NULL)\r
- PyList_SetItem(result, i, getPythonObject(env, item, componentBinding));\r
- else\r
- PyList_SetItem(result, i, Py_None);\r
- }\r
-\r
- return result;\r
-}\r
-\r
-PyObject *getPythonMapObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass objectClass = (*env)->FindClass(env, OBJECT_CLASS);\r
- jclass bindingClass = (*env)->FindClass(env, MAPBINDING_CLASS);\r
- jmethodID getKeyBindingMethod = (*env)->GetMethodID(env, bindingClass, "getKeyBinding", "()L" BINDING_CLASS ";");\r
- jmethodID getValueBindingMethod = (*env)->GetMethodID(env, bindingClass, "getValueBinding", "()L" BINDING_CLASS ";");\r
- jmethodID sizeMethod = (*env)->GetMethodID(env, bindingClass, "size", "(L" OBJECT_CLASS ";)I");\r
- jmethodID getAllMethod = (*env)->GetMethodID(env, bindingClass, "getAll", "(L" OBJECT_CLASS ";[L" OBJECT_CLASS ";[L" OBJECT_CLASS ";)V");\r
-\r
- jobject keyBinding = (*env)->CallObjectMethod(env, binding, getKeyBindingMethod);\r
- jobject valueBinding = (*env)->CallObjectMethod(env, binding, getValueBindingMethod);\r
-\r
- jint size = (*env)->CallIntMethod(env, binding, sizeMethod, object);\r
- jobjectArray keys = (*env)->NewObjectArray(env, size, objectClass, NULL);\r
- jobjectArray values = (*env)->NewObjectArray(env, size, objectClass, NULL);\r
-\r
- PyObject *result = PyDict_New();\r
- jint i;\r
-\r
- (*env)->CallVoidMethod(env, binding, getAllMethod, object, keys, values);\r
-\r
- for (i = 0; i < size; i++) {\r
- jobject key = (*env)->GetObjectArrayElement(env, keys, i);\r
- jobject item = (*env)->GetObjectArrayElement(env, values, i);\r
- PyDict_SetItem(result, getPythonObject(env, key, keyBinding), getPythonObject(env, item, valueBinding));\r
- }\r
-\r
- (*env)->DeleteLocalRef(env, keys);\r
- (*env)->DeleteLocalRef(env, values);\r
-\r
- return result;\r
-}\r
-\r
-PyObject *getPythonOptionalObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, OPTIONALBINDING_CLASS);\r
- jmethodID hasValueMethod = (*env)->GetMethodID(env, bindingClass, "hasValue", "(L" OBJECT_CLASS ";)Z");\r
-\r
- jboolean hasValue = (*env)->CallBooleanMethod(env, binding, hasValueMethod, object);\r
-\r
- if (hasValue) {\r
- jmethodID componentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "()L" BINDING_CLASS ";");\r
- jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "hasValue", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");\r
-\r
- jobject componentBinding = (*env)->CallObjectMethod(env, binding, componentBindingMethod);\r
- jobject value = (*env)->CallObjectMethod(env, binding, getValueMethod, object);\r
-\r
- return getPythonObject(env, value, componentBinding);\r
- }\r
- else {\r
- return Py_None;\r
- }\r
-}\r
-\r
-PyObject *getPythonUnionObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, UNIONBINDING_CLASS);\r
- jmethodID typeMethod = (*env)->GetMethodID(env, bindingClass, "type", "()L" RECORDTYPE_CLASS ";");\r
- jmethodID getTagMethod = (*env)->GetMethodID(env, bindingClass, "getTag", "(L" OBJECT_CLASS ";)I");\r
- jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");\r
- jmethodID getComponentBinding = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "(I)L" BINDING_CLASS ";");\r
-\r
- jclass unionType = (*env)->FindClass(env, UNIONTYPE_CLASS);\r
- jmethodID getTypeComponent = (*env)->GetMethodID(env, unionType, "getComponent", "(I)L" COMPONENT_CLASS ";");\r
-\r
- jclass componentClass = (*env)->FindClass(env, COMPONENT_CLASS);\r
- jfieldID nameField = (*env)->GetFieldID(env, componentClass, "name", "L" STRING_CLASS ";");\r
-\r
- jint tag = (*env)->CallIntMethod(env, binding, getTagMethod, object);\r
- jobject value = (*env)->CallObjectMethod(env, binding, getValueMethod, object);\r
-\r
- jobject type = (*env)->CallObjectMethod(env, binding, typeMethod);\r
- jobject typeComponent = (*env)->CallObjectMethod(env, type, getTypeComponent, tag);\r
- jstring compName = (*env)->GetObjectField(env, typeComponent, nameField);\r
-\r
- jobject componentBinding = (*env)->CallObjectMethod(env, binding, getComponentBinding, tag);\r
-\r
- PyObject *result = PyTuple_New(2);\r
- PyTuple_SetItem(result, 0, getPythonString(env, compName));\r
- PyTuple_SetItem(result, 1, getPythonObject(env, value, componentBinding));\r
-\r
- return result;\r
-}\r
-\r
-PyObject *getPythonVariantObject(JNIEnv *env, jobject object, jobject binding) {\r
- jclass bindingClass = (*env)->FindClass(env, VARIANTBINDING_CLASS);\r
- jmethodID getContentMethod = (*env)->GetMethodID(env, bindingClass, "getContent", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");\r
- jmethodID getContentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getContentBinding", "(L" OBJECT_CLASS ";)L" BINDING_CLASS ";");\r
-\r
- jobject content = (*env)->CallObjectMethod(env, binding, getContentMethod, object);\r
- jobject contentBinding = (*env)->CallObjectMethod(env, binding, getContentBindingMethod, object);\r
-\r
- return getPythonObject(env, content, contentBinding);\r
-}\r
-\r
-PyObject *getPythonObject(JNIEnv *env, jobject value, jobject binding) {\r
- jclass booleanBinding = (*env)->FindClass(env, BOOLEANBINDING_CLASS);\r
- jclass byteBinding = (*env)->FindClass(env, BYTEBINDING_CLASS);\r
- jclass integerBinding = (*env)->FindClass(env, INTEGERBINDING_CLASS);\r
- jclass longBinding = (*env)->FindClass(env, LONGBINDING_CLASS);\r
- jclass floatBinding = (*env)->FindClass(env, FLOATBINDING_CLASS);\r
- jclass doubleBinding = (*env)->FindClass(env, DOUBLEBINDING_CLASS);\r
- jclass stringBinding = (*env)->FindClass(env, STRINGBINDING_CLASS);\r
- jclass recordBinding = (*env)->FindClass(env, RECORDBINDING_CLASS);\r
- jclass arrayBinding = (*env)->FindClass(env, ARRAYBINDING_CLASS);\r
- jclass mapBinding = (*env)->FindClass(env, MAPBINDING_CLASS);\r
- jclass optionalBinding = (*env)->FindClass(env, OPTIONALBINDING_CLASS);\r
- jclass untionBinding = (*env)->FindClass(env, UNIONBINDING_CLASS);\r
- jclass variantBinding = (*env)->FindClass(env, VARIANTBINDING_CLASS);\r
-\r
- if (value == NULL)\r
- return Py_None;\r
-\r
- if ((*env)->IsInstanceOf(env, binding, booleanBinding)) {\r
- return getPythonBooleanObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, byteBinding)) {\r
- return getPythonByteObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, integerBinding)) {\r
- return getPythonIntegerObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, longBinding)) {\r
- return getPythonLongObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, floatBinding)) {\r
- return getPythonFloatObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, doubleBinding)) {\r
- return getPythonDoubleObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, stringBinding)) {\r
- return getPythonStringObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, recordBinding)) {\r
- return getPythonRecordObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, arrayBinding)) {\r
- return getPythonArrayObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, mapBinding)) {\r
- return getPythonMapObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, optionalBinding)) {\r
- return getPythonOptionalObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, untionBinding)) {\r
- return getPythonUnionObject(env, value, binding);\r
- }\r
- else if ((*env)->IsInstanceOf(env, binding, variantBinding)) {\r
- return getPythonVariantObject(env, value, binding);\r
- }\r
- else {\r
- return Py_None;\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
-static 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
-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
- 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 pythonBoolAsBooleanObject(JNIEnv *env, PyObject *value) {\r
- jclass booleanClass = (*env)->FindClass(env, "java/lang/Boolean");\r
- jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, booleanClass, "valueOf", "(Z)Ljava/lang/Boolean;");\r
-\r
- return (*env)->CallStaticObjectMethod(env, booleanClass, valueOfMethod, (jboolean)(value == Py_True));\r
-}\r
-\r
-jobject pythonLongAsLongObject(JNIEnv *env, PyObject *value) {\r
- jclass longClass = (*env)->FindClass(env, "java/lang/Long");\r
- jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, longClass, "valueOf", "(J)Ljava/lang/Long;");\r
-\r
- return (*env)->CallStaticObjectMethod(env, longClass, valueOfMethod, PyLong_AsLongLong(value));\r
-}\r
-\r
-jobject pythonFloatAsDoubleObject(JNIEnv *env, PyObject *value) {\r
- jclass doubleClass = (*env)->FindClass(env, "java/lang/Double");\r
- jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, doubleClass, "valueOf", "(D)Ljava/lang/Double;");\r
-\r
- return (*env)->CallStaticObjectMethod(env, doubleClass, valueOfMethod, PyFloat_AsDouble(value));\r
-}\r
-\r
-jobject pythonByteArrayAsByteArray(JNIEnv *env, PyObject *value) {\r
- Py_ssize_t size = PyByteArray_Size(value);\r
- jbyteArray result = (*env)->NewByteArray(env, (jsize)size);\r
- char *bytes = PyByteArray_AsString(value);\r
-\r
- (*env)->SetByteArrayRegion(env, result, 0, size, bytes);\r
-\r
- return result;\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 pythonSequenceAsStringArray(JNIEnv *env, PyObject *seq) {\r
- Py_ssize_t len = PySequence_Size(seq);\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 = PySequence_GetItem(seq, i);\r
- if (PyUnicode_Check(item)) {\r
- jstring value = pythonStringAsJavaString(env, item);\r
- (*env)->SetObjectArrayElement(env, array, i, value);\r
- }\r
- else {\r
- throwPythonException(env, "List item not a string");\r
- return NULL;\r
- }\r
- }\r
-\r
- return array;\r
-}\r
-\r
-jdoubleArray pythonSequenceAsDoubleArray(JNIEnv *env, PyObject *seq) {\r
- Py_ssize_t len = PySequence_Size(seq);\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 = PySequence_GetItem(seq, i);\r
- if (PyFloat_Check(item)) {\r
- double value = PyFloat_AsDouble(item);\r
- (*env)->SetDoubleArrayRegion(env, array, i, 1, &value);\r
- }\r
- else {\r
- throwPythonException(env, "List item not a floating point value");\r
- return NULL;\r
- }\r
- }\r
-\r
- return array;\r
-}\r
-\r
-jobject pythonObjectAsObject(JNIEnv *env, PyObject *value) {\r
- if (PyBool_Check(value))\r
- return pythonBoolAsBooleanObject(env, value);\r
- else if (PyLong_Check(value))\r
- return pythonLongAsLongObject(env, value);\r
- else if (PyFloat_Check(value))\r
- return pythonFloatAsDoubleObject(env, value);\r
- else if (PyUnicode_Check(value))\r
- return pythonStringAsJavaString(env, value);\r
- else if (PyByteArray_Check(value))\r
- return pythonByteArrayAsByteArray(env, value);\r
- else if (PyDict_Check(value))\r
- return pythonDictionaryAsMap(env, value);\r
- else if (hasNumpy && PyArray_Check(value))\r
- return pythonArrayAsNDArray(env, (PyArrayObject *)value);\r
- else if (PySequence_Check(value))\r
- return pythonSequenceAsObjectArray(env, value);\r
- else\r
- return NULL;\r
-}\r
-\r
-jobjectArray pythonSequenceAsObjectArray(JNIEnv *env, PyObject *seq) {\r
- Py_ssize_t len = PySequence_Size(seq);\r
- jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
- jobjectArray array = (*env)->NewObjectArray(env, jlen, (*env)->FindClass(env, OBJECT_CLASS), NULL);\r
-\r
- jint i;\r
-\r
- for (i = 0; i < jlen; i++) {\r
- PyObject *item = PySequence_GetItem(seq, i);\r
- jobject object = pythonObjectAsObject(env, item);\r
- (*env)->SetObjectArrayElement(env, array, i, object);\r
- }\r
-\r
- return array;\r
-}\r
-\r
-jbooleanArray pythonSequenceAsBooleanArray(JNIEnv *env, PyObject *seq) {\r
- Py_ssize_t len = PySequence_Size(seq);\r
- jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
- jbooleanArray array = (*env)->NewBooleanArray(env, jlen);\r
-\r
- jint i;\r
-\r
- for (i = 0; i < jlen; i++) {\r
- PyObject *item = PySequence_GetItem(seq, i);\r
- if (PyBool_Check(item)) {\r
- jboolean value = item == Py_True;\r
- (*env)->SetBooleanArrayRegion(env, array, i, 1, &value);\r
- }\r
- else {\r
- throwPythonException(env, "List item not a boolean");\r
- return NULL;\r
- }\r
- }\r
-\r
- return array;\r
-}\r
-\r
-jintArray pythonSequenceAsIntegerArray(JNIEnv *env, PyObject *seq) {\r
- Py_ssize_t len = PySequence_Size(seq);\r
- jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
- jintArray array = (*env)->NewIntArray(env, jlen);\r
-\r
- jint i;\r
-\r
- for (i = 0; i < jlen; i++) {\r
- PyObject *item = PySequence_GetItem(seq, i);\r
- if (PyLong_Check(item)) {\r
- jint value = PyLong_AsLong(item);\r
- (*env)->SetIntArrayRegion(env, array, i, 1, &value);\r
- }\r
- else {\r
- throwPythonException(env, "List item not an integer");\r
- return NULL;\r
- }\r
- }\r
-\r
- return array;\r
-}\r
-\r
-jlongArray pythonSequenceAsLongArray(JNIEnv *env, PyObject *seq) {\r
- Py_ssize_t len = PySequence_Size(seq);\r
- jsize jlen = (jsize)min(len, JAVA_MAXINT);\r
- jlongArray array = (*env)->NewLongArray(env, jlen);\r
-\r
- jint i;\r
-\r
- for (i = 0; i < jlen; i++) {\r
- PyObject *item = PySequence_GetItem(seq, i);\r
- if (PyLong_Check(item)) {\r
- jlong value = PyLong_AsLongLong(item);\r
- (*env)->SetLongArrayRegion(env, array, i, 1, &value);\r
- }\r
- else {\r
- throwPythonException(env, "List item not an integer");\r
- return NULL;\r
- }\r
- }\r
-\r
- return array;\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
- throwPythonException(env, "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
-jobject pythonDictionaryAsMap(JNIEnv *env, PyObject *dict) {\r
- jclass hashmapClass = (*env)->FindClass(env, "java/util/HashMap");\r
- jmethodID constructor = (*env)->GetMethodID(env, hashmapClass, "<init>", "(I)V");\r
- jmethodID putMethod = (*env)->GetMethodID(env, hashmapClass, "put", "(L" OBJECT_CLASS ";L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");\r
-\r
- Py_ssize_t size = PyDict_Size(dict);\r
- jobject map = (*env)->NewObject(env, hashmapClass, constructor, (jint)size);\r
-\r
- PyObject *key, *value;\r
- Py_ssize_t pos = 0;\r
-\r
- while (PyDict_Next(dict, &pos, &key, &value)) {\r
- jobject keyObject = pythonObjectAsObject(env, key);\r
- jobject valueObject = pythonObjectAsObject(env, value);\r
- (*env)->CallObjectMethod(env, map, putMethod, keyObject, valueObject);\r
- }\r
-\r
- return map;\r
-}\r
-\r
-JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBooleanVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jboolean value) {\r
- PyObject *module = (PyObject*)contextID;\r
-\r
- PyObject *pythonName = getPythonString(env, variableName);\r
- PyObject *val = getPythonBool(value);\r
-\r
- setPythonVariable(module, pythonName, val);\r
-}\r
-\r
-JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBooleanArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jbooleanArray value) {\r
- PyObject *module = (PyObject*)contextID;\r
-\r
- PyObject *pythonName = getPythonString(env, variableName);\r
- PyObject *val = getPythonBooleanList(env, value);\r
-\r
- setPythonVariable(module, pythonName, val);\r
-}\r
-\r
-JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonLongVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jlong value) {\r
- PyObject *module = (PyObject*)contextID;\r
-\r
- PyObject *pythonName = getPythonString(env, variableName);\r
- PyObject *val = PyLong_FromLongLong(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_setPythonLongArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jlongArray value) {\r
- PyObject *module = (PyObject*)contextID;\r
-\r
- PyObject *pythonName = getPythonString(env, variableName);\r
- PyObject *val = getPythonLongList(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_setPythonFloatArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jfloatArray value) {\r
- PyObject *module = (PyObject*)contextID;\r
-\r
- PyObject *pythonName = getPythonString(env, variableName);\r
- PyObject *val = getPythonFloatList(env, 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 (!hasNumpy) {\r
- throwPythonException(env, "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 void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonVariantVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value, jobject binding) {\r
- PyObject *module = (PyObject*)contextID;\r
-\r
- PyObject *pythonName = getPythonString(env, variableName);\r
- PyObject *val = getPythonObject(env, value, binding);\r
-\r
- setPythonVariable(module, pythonName, val);\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, *traceback;\r
- PyErr_Fetch(&exceptionType, &exception, &traceback);\r
-\r
- {\r
- PyObject *tracebackModule = PyImport_ImportModule("traceback");\r
- if (tracebackModule != NULL) {\r
- PyObject *formatExc = PyDict_GetItemString(PyModule_GetDict(tracebackModule), "format_exception");\r
- if (formatExc != NULL) {\r
- PyObject *args = PyTuple_Pack(3, exceptionType, exception, traceback);\r
- PyObject *message = PyObject_CallObject(formatExc, args);\r
- if (message != NULL) {\r
- PyObject *emptyStr = PyUnicode_FromString("");\r
- PyObject *joined = PyUnicode_Join(emptyStr, message);\r
- char *messageStr = PyUnicode_AsUTF8(joined);\r
- throwPythonException(env, messageStr);\r
- Py_DECREF(joined);\r
- Py_DECREF(emptyStr);\r
- Py_DECREF(message);\r
- }\r
- else {\r
- throwPythonException(env, "Internal error, no message");\r
- }\r
- Py_DECREF(args);\r
- Py_DECREF(formatExc);\r
- }\r
- else {\r
- throwPythonException(env, "Internal error, no format_exc function");\r
- }\r
- Py_DECREF(tracebackModule);\r
- }\r
- else {\r
- throwPythonException(env, "Internal error, no traceback module");\r
- }\r
- }\r
- }\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
- throwPythonException(env, "Python variable not found");\r
- return 0;\r
- }\r
-\r
- if (!PyUnicode_Check(value)) {\r
- throwPythonException(env, "Python variable not a string");\r
- return 0;\r
- }\r
-\r
- {\r
- jstring result = pythonStringAsJavaString(env, value);\r
- return result;\r
- }\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
- throwPythonException(env, "Python variable not found");\r
- return 0;\r
- }\r
-\r
- if (!PySequence_Check(value)) {\r
- throwPythonException(env, "Python variable not a sequence");\r
- return 0;\r
- }\r
-\r
- {\r
- jobjectArray result = pythonSequenceAsStringArray(env, value);\r
- return result;\r
- }\r
-}\r
-\r
-JNIEXPORT jboolean JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonBooleanVariableImpl(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
- throwPythonException(env, "Python variable not found");\r
- return 0;\r
- }\r
-\r
- if (!PyBool_Check(value)) {\r
- throwPythonException(env, "Python variable not a boolean");\r
- return 0;\r
- }\r
-\r
- return value == Py_True;\r
-}\r
-\r
-JNIEXPORT jbooleanArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonBooleanArrayVariableImpl(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
- throwPythonException(env, "Python variable not found");\r
- return 0;\r
- }\r
-\r
- if (!PySequence_Check(value)) {\r
- throwPythonException(env, "Python variable not a sequence");\r
- return 0;\r
- }\r
-\r
- {\r
- jbooleanArray result = pythonSequenceAsBooleanArray(env, value);\r
- return result;\r
- }\r
-}\r
-\r
-JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLongVariableImpl(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
- throwPythonException(env, "Python variable not found");\r
- return 0;\r
- }\r
-\r
- if (!PyLong_Check(value)) {\r
- throwPythonException(env, "Python variable not an integer");\r
- return 0;\r
- }\r
-\r
- {\r
- jlong result = PyLong_AsLongLong(value);\r
- return result;\r
- }\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
- throwPythonException(env, "Python variable not found");\r
- return NULL;\r
- }\r
-\r
- if (!PySequence_Check(value)) {\r
- throwPythonException(env, "Python variable not a sequence");\r
- return NULL;\r
- }\r
-\r
- {\r
- jintArray result = pythonSequenceAsIntegerArray(env, value);\r
- return result;\r
- }\r
-}\r
-\r
-JNIEXPORT jlongArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLongArrayVariableImpl(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
- throwPythonException(env, "Python variable not found");\r
- return NULL;\r
- }\r
-\r
- if (!PySequence_Check(value)) {\r
- throwPythonException(env, "Python variable not a sequence");\r
- return NULL;\r
- }\r
-\r
- {\r
- jlongArray result = pythonSequenceAsLongArray(env, value);\r
- return result;\r
- }\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
- throwPythonException(env, "Python variable not found");\r
- return 0.0;\r
- }\r
-\r
- if (!PyFloat_Check(value)) {\r
- throwPythonException(env, "Python variable not a float");\r
- return 0.0;\r
- }\r
-\r
- {\r
- jdouble result = PyFloat_AsDouble(value);\r
- return result;\r
- }\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
- throwPythonException(env, "Python variable not found");\r
- return NULL;\r
- }\r
-\r
- if (!PySequence_Check(value)) {\r
- throwPythonException(env, "Python variable not a sequence");\r
- return NULL;\r
- }\r
-\r
- {\r
- jdoubleArray result = pythonSequenceAsDoubleArray(env, value);\r
- return result;\r
- }\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 (!hasNumpy) {\r
- throwPythonException(env, "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
- throwPythonException(env, "Python variable not found");\r
- return NULL;\r
- }\r
-\r
- if (!PyArray_Check(value)) {\r
- throwPythonException(env, "Python variable not an ndarray");\r
- return NULL;\r
- }\r
-\r
- if (PyArray_TYPE((PyArrayObject*)value) != NPY_DOUBLE) {\r
- throwPythonException(env, "Only ndarrays of type double are supported");\r
- return NULL;\r
- }\r
-\r
- {\r
- jobject result = pythonArrayAsNDArray(env, (PyArrayObject *)value);\r
- return result;\r
- }\r
- }\r
-}\r
-\r
-JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariantVariableImpl(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
- throwPythonException(env, "Python variable not found");\r
- return NULL;\r
- }\r
-\r
- hasNumpy = _import_array() != -1;\r
-\r
- {\r
- jobject result = pythonObjectAsObject(env, value);\r
- return result;\r
- }\r
-}\r
-\r
-JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariableTypeImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
- PyObject *module = (PyObject*)contextID;\r
- PyObject *dict = PyModule_GetDict(module);\r
-\r
- PyObject *pythonName = getPythonString(env, variableName);\r
-\r
- if (!PyDict_Contains(dict, pythonName)) {\r
- return 0;\r
- }\r
-\r
- {\r
- PyObject *value = PyDict_GetItem(dict, pythonName);\r
-\r
- jint result;\r
-\r
- if (PyBool_Check(value))\r
- result = 1;\r
- else if (PyLong_Check(value))\r
- result = 2;\r
- else if (PyFloat_Check(value))\r
- result = 3;\r
- else if (PyUnicode_Check(value))\r
- result = 4;\r
- else if (PyByteArray_Check(value))\r
- result = 5;\r
- else if (PyDict_Check(value))\r
- result = 6;\r
- else if (hasNumpy && PyArray_Check(value))\r
- result = 7;\r
- else if (PySequence_Check(value))\r
- result = 8;\r
- else\r
- result = -1;\r
-\r
- return result;\r
- }\r
-}\r
-\r
-JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariableNamesImpl(JNIEnv *env, jobject thisObj, jlong contextID) {\r
- PyObject *module = (PyObject*)contextID;\r
- PyObject *dict = PyModule_GetDict(module);\r
-\r
- PyObject *keys = PyDict_Keys(dict);\r
- Py_ssize_t size = PyList_Size(keys);\r
-\r
- jobjectArray result = (*env)->NewObjectArray(env, (jsize)size, (*env)->FindClass(env, STRING_CLASS), NULL);\r
-\r
- Py_ssize_t i;\r
- for (i = 0; i < size; i++) {\r
- jstring javaName = pythonStringAsJavaString(env, PyList_GetItem(keys, i));\r
- (*env)->SetObjectArrayElement(env, result, (jint)i, javaName);\r
- }\r
-\r
- Py_XDECREF(keys);\r
-\r
- return result;\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
- break;\r
-\r
- case DLL_PROCESS_DETACH:\r
- // detach from process\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
+///////////////////////////////////////////////////////
+// //
+// VTT Technical Research Centre of Finland LTD //
+// For internal use only. Do not redistribute. //
+// //
+// Authors: //
+// Antton Tapani ext-antton.tapani@vtt.fi //
+// //
+// Last modified by Antton Tapani 9.2016 //
+// //
+///////////////////////////////////////////////////////
+
+#include "sclpy.h"
+
+#include <windows.h>
+
+jint throwException( JNIEnv *env, char *className, char *message )
+{
+ jclass exClass = (*env)->FindClass( env, className);
+ if (exClass == NULL) {
+ return 0;
+ }
+
+ return (*env)->ThrowNew( env, exClass, message );
+}
+
+jint throwPythonException( JNIEnv *env, char *message ) {
+ return throwException( env, PYTHON_EXCEPTION, message );
+}
+
+jint throwIllegalArgumentException( JNIEnv *env, char *message ) {
+ return throwException( env, ILLEGAL_ARGUMENT_EXCEPTION, message );
+}
+
+int moduleCount = 0;
+int hasNumpy = 0;
+PyThreadState *main_ts = 0;
+
+JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContextImpl(JNIEnv *env, jobject thisObj) {
+ char name[16];
+
+ if (!main_ts) {
+ Py_Initialize();
+
+ hasNumpy = _import_array();
+ hasNumpy = hasNumpy != -1;
+ main_ts = PyEval_SaveThread();
+ }
+
+ sprintf(name, "SCL_%d", ++moduleCount);
+
+ PyEval_RestoreThread(main_ts);
+ {
+ PyObject *module = PyModule_New(name);
+ PyObject *main = PyImport_AddModule("__main__");
+
+ PyDict_Merge(PyModule_GetDict(module), PyModule_GetDict(main), 0);
+ PyEval_SaveThread();
+ return (jlong)module;
+ }
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_deleteContextImpl(JNIEnv *env, jobject thisObj, jlong contextID) {
+ PyObject *module = (PyObject*)contextID;
+ PyEval_RestoreThread(main_ts);
+ Py_XDECREF(module);
+ PyEval_SaveThread();
+}
+
+PyObject *getPythonBool(jboolean value) {
+ if (value) {
+ Py_RETURN_TRUE;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
+}
+
+PyObject *getPythonString(JNIEnv *env, jstring string) {
+ jsize len = (*env)->GetStringLength(env, string);
+ const jchar *chars = (*env)->GetStringChars(env, string, NULL);
+
+ PyObject *value = PyUnicode_DecodeUTF16((char*)chars, 2*len, NULL, NULL);
+
+ (*env)->ReleaseStringChars(env, string, chars);
+ return value;
+}
+
+PyObject *getPythonStringList(JNIEnv *env, jobjectArray value) {
+ jsize nitems = (*env)->GetArrayLength(env, value);
+ jint *values = (*env)->GetIntArrayElements(env, value, NULL);
+ jclass stringClass = (*env)->FindClass(env, STRING_CLASS);
+ jint i;
+
+ PyObject *result = PyList_New(nitems);
+ for (i = 0; i < nitems; i++) {
+ jobject item = (*env)->GetObjectArrayElement(env, value, i);
+ if (item != NULL && (*env)->IsInstanceOf(env, item, stringClass)) {
+ PyList_SetItem(result, i, getPythonString(env, (jstring)item));
+ }
+ else {
+ PyList_SetItem(result, i, Py_None);
+ }
+ }
+
+ (*env)->ReleaseIntArrayElements(env, value, values, JNI_ABORT);
+ return result;
+}
+
+PyObject *getPythonBooleanList(JNIEnv *env, jbooleanArray value) {
+ jsize nitems = (*env)->GetArrayLength(env, value);
+ jboolean *values = (*env)->GetBooleanArrayElements(env, value, NULL);
+ jint i;
+
+ PyObject *result = PyList_New(nitems);
+ for (i = 0; i < nitems; i++) {
+ PyList_SetItem(result, i, getPythonBool(values[i]));
+ }
+
+ (*env)->ReleaseBooleanArrayElements(env, value, values, JNI_ABORT);
+ return result;
+}
+
+PyObject *getPythonByteArray(JNIEnv *env, jbyteArray value) {
+ jint len = (*env)->GetArrayLength(env, value);
+ jbyte *values = (*env)->GetByteArrayElements(env, value, NULL);
+
+ PyObject *result = PyByteArray_FromStringAndSize(values, len);
+
+ (*env)->ReleaseByteArrayElements(env, value, values, JNI_ABORT);
+ return result;
+}
+
+PyObject *getPythonIntegerList(JNIEnv *env, jintArray value) {
+ jsize nitems = (*env)->GetArrayLength(env, value);
+ jint *values = (*env)->GetIntArrayElements(env, value, NULL);
+ jint i;
+
+ PyObject *result = PyList_New(nitems);
+ for (i = 0; i < nitems; i++) {
+ PyList_SetItem(result, i, PyLong_FromLong(values[i]));
+ }
+
+ (*env)->ReleaseIntArrayElements(env, value, values, JNI_ABORT);
+ return result;
+}
+
+PyObject *getPythonLongList(JNIEnv *env, jlongArray value) {
+ jsize nitems = (*env)->GetArrayLength(env, value);
+ jlong *values = (*env)->GetLongArrayElements(env, value, NULL);
+ jint i;
+
+ PyObject *result = PyList_New(nitems);
+ for (i = 0; i < nitems; i++) {
+ PyList_SetItem(result, i, PyLong_FromLongLong(values[i]));
+ }
+
+ (*env)->ReleaseLongArrayElements(env, value, values, JNI_ABORT);
+ return result;
+}
+
+PyObject *getPythonFloatList(JNIEnv *env, jfloatArray value) {
+ jsize nitems = (*env)->GetArrayLength(env, value);
+ float *values = (*env)->GetFloatArrayElements(env, value, NULL);
+ jint i;
+
+ PyObject *result = PyList_New(nitems);
+ for (i = 0; i < nitems; i++) {
+ PyList_SetItem(result, i, PyFloat_FromDouble((double)values[i]));
+ }
+
+ (*env)->ReleaseFloatArrayElements(env, value, values, JNI_ABORT);
+ return result;
+}
+
+PyObject *getPythonDoubleList(JNIEnv *env, jdoubleArray value) {
+ jsize nitems = (*env)->GetArrayLength(env, value);
+ double *values = (*env)->GetDoubleArrayElements(env, value, NULL);
+ jint i;
+
+ PyObject *result = PyList_New(nitems);
+ for (i = 0; i < nitems; i++) {
+ PyList_SetItem(result, i, PyFloat_FromDouble(values[i]));
+ }
+
+ (*env)->ReleaseDoubleArrayElements(env, value, values, JNI_ABORT);
+ return result;
+}
+
+PyObject *getPythonNDArray(JNIEnv *env, jobject value) {
+ jclass ndarrayClass = (*env)->FindClass(env, NDARRAY_CLASS);
+ jmethodID dimsMethod = (*env)->GetMethodID(env, ndarrayClass, "dims", "()[I");
+ jmethodID getValuesMethod = (*env)->GetMethodID(env, ndarrayClass, "getValues", "()[D");
+
+ jintArray jdims = (*env)->CallObjectMethod(env, value, dimsMethod);
+ jsize ndims = (*env)->GetArrayLength(env, jdims);
+ jint *dims = (*env)->GetIntArrayElements(env, jdims, NULL);
+
+ jdoubleArray jvalues = (*env)->CallObjectMethod(env, value, getValuesMethod);
+ jsize len = (*env)->GetArrayLength(env, jvalues);
+ jdouble *values = (*env)->GetDoubleArrayElements(env, jvalues, NULL);
+
+ npy_intp *pyDims = (npy_intp*)malloc(ndims * sizeof(npy_intp));
+
+ jint i, nelem = ndims > 0 ? 1 : 0;
+ for (i = 0; i < ndims; i++) {
+ nelem *= dims[i];
+ pyDims[i] = dims[i];
+ }
+
+ len = min(len, nelem);
+
+ {
+ PyObject *array = PyArray_EMPTY(ndims, pyDims, NPY_DOUBLE, 0);
+ double *data = (double *)PyArray_DATA((PyArrayObject*)array);
+
+ memcpy(data, values, len * sizeof(double));
+
+ free(pyDims);
+
+ (*env)->ReleaseDoubleArrayElements(env, jvalues, values, JNI_ABORT);
+ (*env)->ReleaseIntArrayElements(env, jdims, dims, JNI_ABORT);
+
+ return array;
+ }
+}
+
+PyObject *getPythonBooleanObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, BOOLEANBINDING_CLASS);
+ jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)Z");
+
+ jboolean bvalue = (*env)->CallBooleanMethod(env, binding, getValueMethod, object);
+ return getPythonBool(bvalue);
+}
+
+PyObject *getPythonByteObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, BYTEBINDING_CLASS);
+ jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)B");
+
+ jbyte v = (*env)->CallByteMethod(env, binding, getValueMethod, object);
+ return PyLong_FromLong(v);
+}
+
+PyObject *getPythonIntegerObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, INTEGERBINDING_CLASS);
+ jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)I");
+
+ jint v = (*env)->CallIntMethod(env, binding, getValueMethod, object);
+ return PyLong_FromLong(v);
+}
+
+PyObject *getPythonLongObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, LONGBINDING_CLASS);
+ jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)J");
+
+ jlong v = (*env)->CallLongMethod(env, binding, getValueMethod, object);
+ return PyLong_FromLongLong(v);
+}
+
+PyObject *getPythonFloatObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, FLOATBINDING_CLASS);
+ jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)F");
+
+ jfloat v = (*env)->CallFloatMethod(env, binding, getValueMethod, object);
+ return PyFloat_FromDouble(v);
+}
+
+PyObject *getPythonDoubleObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, DOUBLEBINDING_CLASS);
+ jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)D");
+
+ jdouble v = (*env)->CallDoubleMethod(env, binding, getValueMethod, object);
+ return PyFloat_FromDouble(v);
+}
+
+PyObject *getPythonStringObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, STRINGBINDING_CLASS);
+ jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue", "(L" OBJECT_CLASS ";)L" STRING_CLASS ";");
+
+ jobject string = (*env)->CallObjectMethod(env, binding, getValueMethod, object);
+ jsize len = (*env)->GetStringLength(env, string);
+ const jchar *chars = (*env)->GetStringChars(env, string, NULL);
+
+ PyObject *value = PyUnicode_DecodeUTF16((char*)chars, 2*len, NULL, NULL);
+
+ (*env)->ReleaseStringChars(env, string, chars);
+ return value;
+}
+
+PyObject *getPythonRecordObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, RECORDBINDING_CLASS);
+ jmethodID typeMethod = (*env)->GetMethodID(env, bindingClass, "type", "()L" RECORDTYPE_CLASS ";");
+ jmethodID getComponent = (*env)->GetMethodID(env, bindingClass, "getComponent", "(L" OBJECT_CLASS ";I)L" OBJECT_CLASS ";");
+ jmethodID getComponentBinding = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "(I)L" BINDING_CLASS ";");
+
+ jclass recordType = (*env)->FindClass(env, RECORDTYPE_CLASS);
+ jmethodID getTypeComponent = (*env)->GetMethodID(env, recordType, "getComponent", "(I)L" COMPONENT_CLASS ";");
+ jmethodID getComponentCount = (*env)->GetMethodID(env, recordType, "getComponentCount", "()I");
+
+ jclass componentClass = (*env)->FindClass(env, COMPONENT_CLASS);
+ jfieldID nameField = (*env)->GetFieldID(env, componentClass, "name", "L" STRING_CLASS ";");
+
+ jobject type = (*env)->CallObjectMethod(env, binding, typeMethod);
+ jint n = (*env)->CallIntMethod(env, type, getComponentCount);
+ jint i;
+
+ PyObject *result = PyDict_New();
+ for (i = 0; i < n; i++) {
+ jobject recordTypeComponent = (*env)->CallObjectMethod(env, type, getComponent, i);
+ jstring fieldName = (jstring)(*env)->GetObjectField(env, recordTypeComponent, nameField);
+ jobject componentObject = (*env)->CallObjectMethod(env, binding, getComponent, object, i);
+ jobject componentBinding = (*env)->CallObjectMethod(env, binding, getComponentBinding, i);
+
+ PyObject *item = getPythonObject(env, componentObject, componentBinding);
+ PyDict_SetItem(result, getPythonString(env, fieldName), item);
+ }
+
+ return result;
+}
+
+PyObject *getPythonArrayObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, ARRAYBINDING_CLASS);
+ jmethodID componentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "()L" BINDING_CLASS ";");
+ jmethodID sizeMethod = (*env)->GetMethodID(env, bindingClass, "size", "(L" OBJECT_CLASS ";)I");
+ jmethodID getMethod = (*env)->GetMethodID(env, bindingClass, "get", "(L" OBJECT_CLASS ";I)L" OBJECT_CLASS ";");
+
+ jobject componentBinding = (*env)->CallObjectMethod(env, binding, componentBindingMethod);
+
+ jint size = (*env)->CallIntMethod(env, binding, sizeMethod, object);
+
+ PyObject *result = PyList_New(size);
+
+ jint i;
+ for (i = 0; i < size; i++) {
+ jobject item = (*env)->CallObjectMethod(env, binding, getMethod, object, i);
+ if (item != NULL)
+ PyList_SetItem(result, i, getPythonObject(env, item, componentBinding));
+ else
+ PyList_SetItem(result, i, Py_None);
+ }
+
+ return result;
+}
+
+PyObject *getPythonMapObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass objectClass = (*env)->FindClass(env, OBJECT_CLASS);
+ jclass bindingClass = (*env)->FindClass(env, MAPBINDING_CLASS);
+ jmethodID getKeyBindingMethod = (*env)->GetMethodID(env, bindingClass, "getKeyBinding", "()L" BINDING_CLASS ";");
+ jmethodID getValueBindingMethod = (*env)->GetMethodID(env, bindingClass, "getValueBinding", "()L" BINDING_CLASS ";");
+ jmethodID sizeMethod = (*env)->GetMethodID(env, bindingClass, "size", "(L" OBJECT_CLASS ";)I");
+ jmethodID getAllMethod = (*env)->GetMethodID(env, bindingClass, "getAll", "(L" OBJECT_CLASS ";[L" OBJECT_CLASS ";[L" OBJECT_CLASS ";)V");
+
+ jobject keyBinding = (*env)->CallObjectMethod(env, binding, getKeyBindingMethod);
+ jobject valueBinding = (*env)->CallObjectMethod(env, binding, getValueBindingMethod);
+
+ jint size = (*env)->CallIntMethod(env, binding, sizeMethod, object);
+ jobjectArray keys = (*env)->NewObjectArray(env, size, objectClass, NULL);
+ jobjectArray values = (*env)->NewObjectArray(env, size, objectClass, NULL);
+
+ PyObject *result = PyDict_New();
+ jint i;
+
+ (*env)->CallVoidMethod(env, binding, getAllMethod, object, keys, values);
+
+ for (i = 0; i < size; i++) {
+ jobject key = (*env)->GetObjectArrayElement(env, keys, i);
+ jobject item = (*env)->GetObjectArrayElement(env, values, i);
+ PyDict_SetItem(result, getPythonObject(env, key, keyBinding), getPythonObject(env, item, valueBinding));
+ }
+
+ (*env)->DeleteLocalRef(env, keys);
+ (*env)->DeleteLocalRef(env, values);
+
+ return result;
+}
+
+PyObject *getPythonOptionalObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, OPTIONALBINDING_CLASS);
+ jmethodID hasValueMethod = (*env)->GetMethodID(env, bindingClass, "hasValue", "(L" OBJECT_CLASS ";)Z");
+
+ jboolean hasValue = (*env)->CallBooleanMethod(env, binding, hasValueMethod, object);
+
+ if (hasValue) {
+ jmethodID componentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "()L" BINDING_CLASS ";");
+ jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "hasValue", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");
+
+ jobject componentBinding = (*env)->CallObjectMethod(env, binding, componentBindingMethod);
+ jobject value = (*env)->CallObjectMethod(env, binding, getValueMethod, object);
+
+ return getPythonObject(env, value, componentBinding);
+ }
+ else {
+ return Py_None;
+ }
+}
+
+PyObject *getPythonUnionObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, UNIONBINDING_CLASS);
+ jmethodID typeMethod = (*env)->GetMethodID(env, bindingClass, "type", "()L" RECORDTYPE_CLASS ";");
+ jmethodID getTagMethod = (*env)->GetMethodID(env, bindingClass, "getTag", "(L" OBJECT_CLASS ";)I");
+ jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");
+ jmethodID getComponentBinding = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "(I)L" BINDING_CLASS ";");
+
+ jclass unionType = (*env)->FindClass(env, UNIONTYPE_CLASS);
+ jmethodID getTypeComponent = (*env)->GetMethodID(env, unionType, "getComponent", "(I)L" COMPONENT_CLASS ";");
+
+ jclass componentClass = (*env)->FindClass(env, COMPONENT_CLASS);
+ jfieldID nameField = (*env)->GetFieldID(env, componentClass, "name", "L" STRING_CLASS ";");
+
+ jint tag = (*env)->CallIntMethod(env, binding, getTagMethod, object);
+ jobject value = (*env)->CallObjectMethod(env, binding, getValueMethod, object);
+
+ jobject type = (*env)->CallObjectMethod(env, binding, typeMethod);
+ jobject typeComponent = (*env)->CallObjectMethod(env, type, getTypeComponent, tag);
+ jstring compName = (*env)->GetObjectField(env, typeComponent, nameField);
+
+ jobject componentBinding = (*env)->CallObjectMethod(env, binding, getComponentBinding, tag);
+
+ PyObject *result = PyTuple_New(2);
+ PyTuple_SetItem(result, 0, getPythonString(env, compName));
+ PyTuple_SetItem(result, 1, getPythonObject(env, value, componentBinding));
+
+ return result;
+}
+
+PyObject *getPythonVariantObject(JNIEnv *env, jobject object, jobject binding) {
+ jclass bindingClass = (*env)->FindClass(env, VARIANTBINDING_CLASS);
+ jmethodID getContentMethod = (*env)->GetMethodID(env, bindingClass, "getContent", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");
+ jmethodID getContentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getContentBinding", "(L" OBJECT_CLASS ";)L" BINDING_CLASS ";");
+
+ jobject content = (*env)->CallObjectMethod(env, binding, getContentMethod, object);
+ jobject contentBinding = (*env)->CallObjectMethod(env, binding, getContentBindingMethod, object);
+
+ return getPythonObject(env, content, contentBinding);
+}
+
+PyObject *getPythonObject(JNIEnv *env, jobject value, jobject binding) {
+ jclass booleanBinding = (*env)->FindClass(env, BOOLEANBINDING_CLASS);
+ jclass byteBinding = (*env)->FindClass(env, BYTEBINDING_CLASS);
+ jclass integerBinding = (*env)->FindClass(env, INTEGERBINDING_CLASS);
+ jclass longBinding = (*env)->FindClass(env, LONGBINDING_CLASS);
+ jclass floatBinding = (*env)->FindClass(env, FLOATBINDING_CLASS);
+ jclass doubleBinding = (*env)->FindClass(env, DOUBLEBINDING_CLASS);
+ jclass stringBinding = (*env)->FindClass(env, STRINGBINDING_CLASS);
+ jclass recordBinding = (*env)->FindClass(env, RECORDBINDING_CLASS);
+ jclass arrayBinding = (*env)->FindClass(env, ARRAYBINDING_CLASS);
+ jclass mapBinding = (*env)->FindClass(env, MAPBINDING_CLASS);
+ jclass optionalBinding = (*env)->FindClass(env, OPTIONALBINDING_CLASS);
+ jclass untionBinding = (*env)->FindClass(env, UNIONBINDING_CLASS);
+ jclass variantBinding = (*env)->FindClass(env, VARIANTBINDING_CLASS);
+
+ if (value == NULL)
+ return Py_None;
+
+ if ((*env)->IsInstanceOf(env, binding, booleanBinding)) {
+ return getPythonBooleanObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, byteBinding)) {
+ return getPythonByteObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, integerBinding)) {
+ return getPythonIntegerObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, longBinding)) {
+ return getPythonLongObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, floatBinding)) {
+ return getPythonFloatObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, doubleBinding)) {
+ return getPythonDoubleObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, stringBinding)) {
+ return getPythonStringObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, recordBinding)) {
+ return getPythonRecordObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, arrayBinding)) {
+ return getPythonArrayObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, mapBinding)) {
+ return getPythonMapObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, optionalBinding)) {
+ return getPythonOptionalObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, untionBinding)) {
+ return getPythonUnionObject(env, value, binding);
+ }
+ else if ((*env)->IsInstanceOf(env, binding, variantBinding)) {
+ return getPythonVariantObject(env, value, binding);
+ }
+ else {
+ return Py_None;
+ }
+}
+
+void setPythonVariable(PyObject *module, PyObject *name, PyObject *value) {
+ if (name && value) {
+ PyDict_SetItem(PyModule_GetDict(module), name, value);
+ }
+
+ Py_XDECREF(name);
+ Py_XDECREF(value);
+}
+
+static npy_intp nContiguous(int d, int nd, npy_intp *strides, npy_intp *dims, npy_intp *ncont) {
+ if (d == nd) {
+ ncont[d] = 1;
+ return 1;
+ }
+ else {
+ npy_intp n = nContiguous(d+1, nd, strides, dims, ncont);
+ ncont[d] = n > 0 && strides[d] == sizeof(double) * n ? dims[d] * n : 0;
+ return ncont[d];
+ }
+}
+
+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) {
+ if (ncont[d] > 0) {
+ (*env)->SetDoubleArrayRegion(env, array, (jint)*offset, (jint)ncont[d], data);
+ *offset += ncont[d];
+ }
+ else {
+ int i;
+ for (i = 0; i < dims[d]; i++) {
+ copyDoubleArrayValues(env, array, (double*)((char*)data + strides[d] * i), offset, d+1, nd, strides, dims, ncont);
+ }
+ }
+}
+
+jobject pythonBoolAsBooleanObject(JNIEnv *env, PyObject *value) {
+ jclass booleanClass = (*env)->FindClass(env, "java/lang/Boolean");
+ jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, booleanClass, "valueOf", "(Z)Ljava/lang/Boolean;");
+
+ return (*env)->CallStaticObjectMethod(env, booleanClass, valueOfMethod, (jboolean)(value == Py_True));
+}
+
+jobject pythonLongAsLongObject(JNIEnv *env, PyObject *value) {
+ jclass longClass = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, longClass, "valueOf", "(J)Ljava/lang/Long;");
+
+ return (*env)->CallStaticObjectMethod(env, longClass, valueOfMethod, PyLong_AsLongLong(value));
+}
+
+jobject pythonFloatAsDoubleObject(JNIEnv *env, PyObject *value) {
+ jclass doubleClass = (*env)->FindClass(env, "java/lang/Double");
+ jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, doubleClass, "valueOf", "(D)Ljava/lang/Double;");
+
+ return (*env)->CallStaticObjectMethod(env, doubleClass, valueOfMethod, PyFloat_AsDouble(value));
+}
+
+jobject pythonByteArrayAsByteArray(JNIEnv *env, PyObject *value) {
+ Py_ssize_t size = PyByteArray_Size(value);
+ jbyteArray result = (*env)->NewByteArray(env, (jsize)size);
+ char *bytes = PyByteArray_AsString(value);
+
+ (*env)->SetByteArrayRegion(env, result, 0, size, bytes);
+
+ return result;
+}
+
+jstring pythonStringAsJavaString(JNIEnv *env, PyObject *string) {
+ PyObject *utf16Value = PyUnicode_AsUTF16String(string);
+ Py_ssize_t len = PyBytes_Size(utf16Value) / 2;
+ char *bytes = PyBytes_AsString(utf16Value);
+
+ // Create Java string, skipping the byte order mark in the beginning
+ jstring result = (*env)->NewString(env, (jchar *)bytes + 1, (jsize)min(len, JAVA_MAXINT) - 1);
+
+ Py_XDECREF(utf16Value);
+
+ return result;
+}
+
+jobjectArray pythonSequenceAsStringArray(JNIEnv *env, PyObject *seq) {
+ Py_ssize_t len = PySequence_Size(seq);
+ jsize jlen = (jsize)min(len, JAVA_MAXINT);
+ jobjectArray array = (*env)->NewObjectArray(env, jlen, (*env)->FindClass(env, STRING_CLASS), NULL);
+
+ jint i;
+
+ for (i = 0; i < jlen; i++) {
+ PyObject *item = PySequence_GetItem(seq, i);
+ if (PyUnicode_Check(item)) {
+ jstring value = pythonStringAsJavaString(env, item);
+ (*env)->SetObjectArrayElement(env, array, i, value);
+ }
+ else {
+ throwPythonException(env, "List item not a string");
+ return NULL;
+ }
+ }
+
+ return array;
+}
+
+jdoubleArray pythonSequenceAsDoubleArray(JNIEnv *env, PyObject *seq) {
+ Py_ssize_t len = PySequence_Size(seq);
+ jsize jlen = (jsize)min(len, JAVA_MAXINT);
+ jdoubleArray array = (*env)->NewDoubleArray(env, jlen);
+
+ jint i;
+
+ for (i = 0; i < jlen; i++) {
+ PyObject *item = PySequence_GetItem(seq, i);
+ if (PyFloat_Check(item)) {
+ double value = PyFloat_AsDouble(item);
+ (*env)->SetDoubleArrayRegion(env, array, i, 1, &value);
+ }
+ else {
+ throwPythonException(env, "List item not a floating point value");
+ return NULL;
+ }
+ }
+
+ return array;
+}
+
+jobject pythonObjectAsObject(JNIEnv *env, PyObject *value) {
+ if (PyBool_Check(value))
+ return pythonBoolAsBooleanObject(env, value);
+ else if (PyLong_Check(value))
+ return pythonLongAsLongObject(env, value);
+ else if (PyFloat_Check(value))
+ return pythonFloatAsDoubleObject(env, value);
+ else if (PyUnicode_Check(value))
+ return pythonStringAsJavaString(env, value);
+ else if (PyByteArray_Check(value))
+ return pythonByteArrayAsByteArray(env, value);
+ else if (PyDict_Check(value))
+ return pythonDictionaryAsMap(env, value);
+ else if (hasNumpy && PyArray_Check(value))
+ return pythonArrayAsNDArray(env, (PyArrayObject *)value);
+ else if (PySequence_Check(value))
+ return pythonSequenceAsObjectArray(env, value);
+ else
+ return NULL;
+}
+
+jobjectArray pythonSequenceAsObjectArray(JNIEnv *env, PyObject *seq) {
+ Py_ssize_t len = PySequence_Size(seq);
+ jsize jlen = (jsize)min(len, JAVA_MAXINT);
+ jobjectArray array = (*env)->NewObjectArray(env, jlen, (*env)->FindClass(env, OBJECT_CLASS), NULL);
+
+ jint i;
+
+ for (i = 0; i < jlen; i++) {
+ PyObject *item = PySequence_GetItem(seq, i);
+ jobject object = pythonObjectAsObject(env, item);
+ (*env)->SetObjectArrayElement(env, array, i, object);
+ }
+
+ return array;
+}
+
+jbooleanArray pythonSequenceAsBooleanArray(JNIEnv *env, PyObject *seq) {
+ Py_ssize_t len = PySequence_Size(seq);
+ jsize jlen = (jsize)min(len, JAVA_MAXINT);
+ jbooleanArray array = (*env)->NewBooleanArray(env, jlen);
+
+ jint i;
+
+ for (i = 0; i < jlen; i++) {
+ PyObject *item = PySequence_GetItem(seq, i);
+ if (PyBool_Check(item)) {
+ jboolean value = item == Py_True;
+ (*env)->SetBooleanArrayRegion(env, array, i, 1, &value);
+ }
+ else {
+ throwPythonException(env, "List item not a boolean");
+ return NULL;
+ }
+ }
+
+ return array;
+}
+
+jintArray pythonSequenceAsIntegerArray(JNIEnv *env, PyObject *seq) {
+ Py_ssize_t len = PySequence_Size(seq);
+ jsize jlen = (jsize)min(len, JAVA_MAXINT);
+ jintArray array = (*env)->NewIntArray(env, jlen);
+
+ jint i;
+
+ for (i = 0; i < jlen; i++) {
+ PyObject *item = PySequence_GetItem(seq, i);
+ if (PyLong_Check(item)) {
+ jint value = PyLong_AsLong(item);
+ (*env)->SetIntArrayRegion(env, array, i, 1, &value);
+ }
+ else {
+ throwPythonException(env, "List item not an integer");
+ return NULL;
+ }
+ }
+
+ return array;
+}
+
+jlongArray pythonSequenceAsLongArray(JNIEnv *env, PyObject *seq) {
+ Py_ssize_t len = PySequence_Size(seq);
+ jsize jlen = (jsize)min(len, JAVA_MAXINT);
+ jlongArray array = (*env)->NewLongArray(env, jlen);
+
+ jint i;
+
+ for (i = 0; i < jlen; i++) {
+ PyObject *item = PySequence_GetItem(seq, i);
+ if (PyLong_Check(item)) {
+ jlong value = PyLong_AsLongLong(item);
+ (*env)->SetLongArrayRegion(env, array, i, 1, &value);
+ }
+ else {
+ throwPythonException(env, "List item not an integer");
+ return NULL;
+ }
+ }
+
+ return array;
+}
+
+jobject pythonArrayAsNDArray(JNIEnv *env, PyArrayObject *array) {
+ jclass ndarrayClass = (*env)->FindClass(env, NDARRAY_CLASS);
+ jmethodID constructor = (*env)->GetMethodID(env, ndarrayClass, "<init>", "([I[D)V");
+
+ int ndims = PyArray_NDIM(array);
+ npy_intp *dims = PyArray_DIMS(array);
+
+ npy_intp len = PyArray_Size((PyObject*)array);
+ double *values = (double*)PyArray_DATA(array);
+
+ jboolean isFortran = PyArray_ISFORTRAN(array) != 0;
+
+ int i;
+
+ if (len > JAVA_MAXINT) {
+ throwPythonException(env, "Array too large");
+ return NULL;
+ }
+
+ {
+ jintArray jdims = (*env)->NewIntArray(env, ndims);
+ jdoubleArray jvalues = (*env)->NewDoubleArray(env, (jsize)len);
+
+ for (i = 0; i < ndims; i++) {
+ jint dim = (jint)dims[i];
+ (*env)->SetIntArrayRegion(env, jdims, i, 1, &dim);
+ }
+
+ if (PyArray_IS_C_CONTIGUOUS(array)) {
+ (*env)->SetDoubleArrayRegion(env, jvalues, 0, (jsize)len, values);
+ }
+ else {
+ npy_intp offset = 0;
+ npy_intp *strides = PyArray_STRIDES(array);
+ npy_intp *ncont = (npy_intp*)malloc((ndims + 1) * sizeof(npy_intp));
+ nContiguous(0, ndims, strides, dims, ncont);
+ copyDoubleArrayValues(env, jvalues, values, &offset, 0, ndims, strides, dims, ncont);
+ free(ncont);
+ }
+
+ return (*env)->NewObject(env, ndarrayClass, constructor, jdims, jvalues, isFortran);
+ }
+}
+
+jobject pythonDictionaryAsMap(JNIEnv *env, PyObject *dict) {
+ jclass hashmapClass = (*env)->FindClass(env, "java/util/HashMap");
+ jmethodID constructor = (*env)->GetMethodID(env, hashmapClass, "<init>", "(I)V");
+ jmethodID putMethod = (*env)->GetMethodID(env, hashmapClass, "put", "(L" OBJECT_CLASS ";L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");
+
+ Py_ssize_t size = PyDict_Size(dict);
+ jobject map = (*env)->NewObject(env, hashmapClass, constructor, (jint)size);
+
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next(dict, &pos, &key, &value)) {
+ jobject keyObject = pythonObjectAsObject(env, key);
+ jobject valueObject = pythonObjectAsObject(env, value);
+ (*env)->CallObjectMethod(env, map, putMethod, keyObject, valueObject);
+ }
+
+ return map;
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBooleanVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jboolean value) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = getPythonBool(value);
+
+ setPythonVariable(module, pythonName, val);
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBooleanArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jbooleanArray value) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = getPythonBooleanList(env, value);
+
+ setPythonVariable(module, pythonName, val);
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonLongVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jlong value) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = PyLong_FromLongLong(value);
+
+ setPythonVariable(module, pythonName, val);
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jintArray value) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = getPythonIntegerList(env, value);
+
+ setPythonVariable(module, pythonName, val);
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonLongArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jlongArray value) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = getPythonLongList(env, value);
+
+ setPythonVariable(module, pythonName, val);
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdouble value) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = PyFloat_FromDouble(value);
+
+ setPythonVariable(module, pythonName, val);
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonFloatArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jfloatArray value) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = getPythonFloatList(env, value);
+
+ setPythonVariable(module, pythonName, val);
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdoubleArray value) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = getPythonDoubleList(env, value);
+
+ setPythonVariable(module, pythonName, val);
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jstring value) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = getPythonString(env, value);
+
+ setPythonVariable(module, pythonName, val);
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobjectArray value) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = getPythonStringList(env, value);
+
+ setPythonVariable(module, pythonName, val);
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value) {
+ PyObject *module = (PyObject*)contextID;
+
+ if (!hasNumpy) {
+ throwPythonException(env, "Importing numpy failed");
+ return;
+ }
+
+ {
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = getPythonNDArray(env, value);
+
+ setPythonVariable(module, pythonName, val);
+ }
+}
+
+JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonVariantVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value, jobject binding) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+ PyObject *val = getPythonObject(env, value, binding);
+
+ setPythonVariable(module, pythonName, val);
+}
+
+JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePythonStatementImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring statement) {
+ PyObject *module = (PyObject*)contextID;
+
+ const char *utfchars = (*env)->GetStringUTFChars(env, statement, NULL);
+
+ PyEval_RestoreThread(main_ts);
+ PyErr_Clear();
+ {
+ PyObject *globals;
+
+ globals = PyModule_GetDict(module);
+
+ {
+ PyObject *result = PyRun_String(utfchars, Py_file_input, globals, globals);
+
+ PyObject *exceptionType = PyErr_Occurred();
+ if (exceptionType != NULL) {
+ PyObject *exception, *traceback;
+ PyErr_Fetch(&exceptionType, &exception, &traceback);
+
+ {
+ PyObject *tracebackModule = PyImport_ImportModule("traceback");
+ if (tracebackModule != NULL) {
+ PyObject *formatExc = PyDict_GetItemString(PyModule_GetDict(tracebackModule), "format_exception");
+ if (formatExc != NULL) {
+ PyObject *args = PyTuple_Pack(3, exceptionType, exception, traceback);
+ PyObject *message = PyObject_CallObject(formatExc, args);
+ if (message != NULL) {
+ PyObject *emptyStr = PyUnicode_FromString("");
+ PyObject *joined = PyUnicode_Join(emptyStr, message);
+ char *messageStr = PyUnicode_AsUTF8(joined);
+ throwPythonException(env, messageStr);
+ Py_DECREF(joined);
+ Py_DECREF(emptyStr);
+ Py_DECREF(message);
+ }
+ else {
+ throwPythonException(env, "Internal error, no message");
+ }
+ Py_DECREF(args);
+ Py_DECREF(formatExc);
+ }
+ else {
+ throwPythonException(env, "Internal error, no format_exc function");
+ }
+ Py_DECREF(tracebackModule);
+ }
+ else {
+ throwPythonException(env, "Internal error, no traceback module");
+ }
+ }
+ }
+
+ PyEval_SaveThread();
+ (*env)->ReleaseStringUTFChars(env, statement, utfchars);
+
+ return result != NULL ? 0 : 1;
+ }
+ }
+}
+
+JNIEXPORT jstring JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
+ if (value == NULL) {
+ throwPythonException(env, "Python variable not found");
+ return 0;
+ }
+
+ if (!PyUnicode_Check(value)) {
+ throwPythonException(env, "Python variable not a string");
+ return 0;
+ }
+
+ {
+ jstring result = pythonStringAsJavaString(env, value);
+ return result;
+ }
+}
+
+JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
+ if (value == NULL) {
+ throwPythonException(env, "Python variable not found");
+ return 0;
+ }
+
+ if (!PySequence_Check(value)) {
+ throwPythonException(env, "Python variable not a sequence");
+ return 0;
+ }
+
+ {
+ jobjectArray result = pythonSequenceAsStringArray(env, value);
+ return result;
+ }
+}
+
+JNIEXPORT jboolean JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonBooleanVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
+ if (value == NULL) {
+ throwPythonException(env, "Python variable not found");
+ return 0;
+ }
+
+ if (!PyBool_Check(value)) {
+ throwPythonException(env, "Python variable not a boolean");
+ return 0;
+ }
+
+ return value == Py_True;
+}
+
+JNIEXPORT jbooleanArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonBooleanArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
+ if (value == NULL) {
+ throwPythonException(env, "Python variable not found");
+ return 0;
+ }
+
+ if (!PySequence_Check(value)) {
+ throwPythonException(env, "Python variable not a sequence");
+ return 0;
+ }
+
+ {
+ jbooleanArray result = pythonSequenceAsBooleanArray(env, value);
+ return result;
+ }
+}
+
+JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLongVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
+ if (value == NULL) {
+ throwPythonException(env, "Python variable not found");
+ return 0;
+ }
+
+ if (!PyLong_Check(value)) {
+ throwPythonException(env, "Python variable not an integer");
+ return 0;
+ }
+
+ {
+ jlong result = PyLong_AsLongLong(value);
+ return result;
+ }
+}
+
+JNIEXPORT jintArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
+ if (value == NULL) {
+ throwPythonException(env, "Python variable not found");
+ return NULL;
+ }
+
+ if (!PySequence_Check(value)) {
+ throwPythonException(env, "Python variable not a sequence");
+ return NULL;
+ }
+
+ {
+ jintArray result = pythonSequenceAsIntegerArray(env, value);
+ return result;
+ }
+}
+
+JNIEXPORT jlongArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLongArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
+ if (value == NULL) {
+ throwPythonException(env, "Python variable not found");
+ return NULL;
+ }
+
+ if (!PySequence_Check(value)) {
+ throwPythonException(env, "Python variable not a sequence");
+ return NULL;
+ }
+
+ {
+ jlongArray result = pythonSequenceAsLongArray(env, value);
+ return result;
+ }
+}
+
+JNIEXPORT jdouble JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
+ if (value == NULL) {
+ throwPythonException(env, "Python variable not found");
+ return 0.0;
+ }
+
+ if (!PyFloat_Check(value)) {
+ throwPythonException(env, "Python variable not a float");
+ return 0.0;
+ }
+
+ {
+ jdouble result = PyFloat_AsDouble(value);
+ return result;
+ }
+}
+
+JNIEXPORT jdoubleArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
+ if (value == NULL) {
+ throwPythonException(env, "Python variable not found");
+ return NULL;
+ }
+
+ if (!PySequence_Check(value)) {
+ throwPythonException(env, "Python variable not a sequence");
+ return NULL;
+ }
+
+ {
+ jdoubleArray result = pythonSequenceAsDoubleArray(env, value);
+ return result;
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+
+ if (!hasNumpy) {
+ throwPythonException(env, "Importing numpy failed");
+ return NULL;
+ }
+
+ {
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
+ if (value == NULL) {
+ throwPythonException(env, "Python variable not found");
+ return NULL;
+ }
+
+ if (!PyArray_Check(value)) {
+ throwPythonException(env, "Python variable not an ndarray");
+ return NULL;
+ }
+
+ if (PyArray_TYPE((PyArrayObject*)value) != NPY_DOUBLE) {
+ throwPythonException(env, "Only ndarrays of type double are supported");
+ return NULL;
+ }
+
+ {
+ jobject result = pythonArrayAsNDArray(env, (PyArrayObject *)value);
+ return result;
+ }
+ }
+}
+
+JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariantVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
+ if (value == NULL) {
+ throwPythonException(env, "Python variable not found");
+ return NULL;
+ }
+
+ hasNumpy = _import_array() != -1;
+
+ {
+ jobject result = pythonObjectAsObject(env, value);
+ return result;
+ }
+}
+
+JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariableTypeImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+ PyObject *module = (PyObject*)contextID;
+ PyObject *dict = PyModule_GetDict(module);
+
+ PyObject *pythonName = getPythonString(env, variableName);
+
+ if (!PyDict_Contains(dict, pythonName)) {
+ return 0;
+ }
+
+ {
+ PyObject *value = PyDict_GetItem(dict, pythonName);
+
+ jint result;
+
+ if (PyBool_Check(value))
+ result = 1;
+ else if (PyLong_Check(value))
+ result = 2;
+ else if (PyFloat_Check(value))
+ result = 3;
+ else if (PyUnicode_Check(value))
+ result = 4;
+ else if (PyByteArray_Check(value))
+ result = 5;
+ else if (PyDict_Check(value))
+ result = 6;
+ else if (hasNumpy && PyArray_Check(value))
+ result = 7;
+ else if (PySequence_Check(value))
+ result = 8;
+ else
+ result = -1;
+
+ return result;
+ }
+}
+
+JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariableNamesImpl(JNIEnv *env, jobject thisObj, jlong contextID) {
+ PyObject *module = (PyObject*)contextID;
+ PyObject *dict = PyModule_GetDict(module);
+
+ PyObject *keys = PyDict_Keys(dict);
+ Py_ssize_t size = PyList_Size(keys);
+
+ jobjectArray result = (*env)->NewObjectArray(env, (jsize)size, (*env)->FindClass(env, STRING_CLASS), NULL);
+
+ Py_ssize_t i;
+ for (i = 0; i < size; i++) {
+ jstring javaName = pythonStringAsJavaString(env, PyList_GetItem(keys, i));
+ (*env)->SetObjectArrayElement(env, result, (jint)i, javaName);
+ }
+
+ Py_XDECREF(keys);
+
+ return result;
+}
+
+BOOL __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+//extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ // attach to process
+ // return FALSE to fail DLL load
+ break;
+
+ case DLL_PROCESS_DETACH:
+ // detach from process
+ break;
+
+ case DLL_THREAD_ATTACH:
+ // attach to thread
+ break;
+
+ case DLL_THREAD_DETACH:
+ // detach from thread
+ break;
+ }
+ return TRUE; // succesful
+}