From 94a19dbaf6ef04f3476ac6d51c5b8f29f237cf23 Mon Sep 17 00:00:00 2001 From: Timo Korvola Date: Fri, 27 Jan 2017 16:04:24 +0200 Subject: [PATCH] Add some PyEval_{Restore,Save}Thread calls. More are needed, but it is a mess of copy-paste programming. Change-Id: Ie4dcc7627349cab84c37cb0b6c7275876373e25d --- .../jnipython.dll | Bin 33792 -> 62976 bytes .../src/sclpy.c | 2581 +++++++++-------- 2 files changed, 1293 insertions(+), 1288 deletions(-) diff --git a/org.simantics.pythonlink.win32.x86_64/jnipython.dll b/org.simantics.pythonlink.win32.x86_64/jnipython.dll index 7fff774adac1bb1b1d2c5ffbffa6043e44d877e1..37e45770533af445a425847d0cc431e9065461ac 100644 GIT binary patch literal 62976 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 HXMz6*&g|9J literal 33792 zcmeHw3w%`7wfCMR69Obmcnk#OF-YhQw^kwn1p}Hf37(OO1_;O%G#Mrnh=yc3nX%A| zhz8X3kT$-mwq8qXANISprLC=EZ`;ry4|zp=fzMbUcQAU5j{;V`=l<8)`^=n~Ob8Y4 z{qFDkI{eP8efDGRwbovH?X}n56DqE17wJNX3_OM*#AAT;DdF!^fAykx*rdmYiAM$> znEaT{dth?a>iT9^Fx0dvb7eIVCEDBZP~Tt2 zWBHT_(Q$52R%9NxqA(NBdOVg-3E>L`8k+n%-<-Ax01K@1K&}#ZgZF5J&rRh1h&}*CX9+YYNV8giq?=5=_t!1aHx)TMBT(C!L zU6EgCI9F3`!=dR%B11I&$}CMkWGpJwHoq8|3S5gMt|=z28T78BVH}}upGBE-O0&YV z(V|ec*t=NuPI{*qLmit1rkSRfqJw=#Wnm(cqQjKy{B$AL)mrTr-Y7(5xV5_dACN^X z5?TAGVwI*oYCg|11Rd5YP8=AEp9mprtSMt zrFo{zaX$u|LdY*A!u6aQpf1z*up}G$cGKPtETC#ITD*+np6r&Bw(wNEeT^&UxENp< zrXxX8BQoV!6m?i$_FFzQG+8vpB_PfL;t6UaR|C$IP;J$CyF78rw!+DF50c>UT{;iKk6x=HY@Tg!CFamr-d0L z!AU{I=8mw#V`N2!c=VDi570viT6PvtRpwV~ZOG5nTEqEyQoD5w-Upg~%xHJPJbCpB z+5K~xen3CsHf}FKZdqH#S>;80J^n6}G?0J(6|%Zl2YFN-^rLT7yKK9n?^U!v)q z{RkiQlq_Dd^h)*Qzhe_sKr!>yh5k`Y3b3goyvD0%dh};GPl=2um02-~wPlmQH2+f=NR}A{ zW(QRgr>q>8msjuf=+AicgNE}+g%B9u8ckoHAM6?F)$PwA$1HsuY2yixv9q|xv1OiN z7+y%)<<-HRre}I}62^8~T_jURdmg5ZN8d#n;I4LGQ+>_V%i~Iuqz_u_dgyMIdx?7~ z+dUeP54@xqG$0jHGd%ip9t^dghWasN!=QNe*EPM@a5_O;5hh+#f3;%s8ynp18|M~@ z@JLMVvrwWLKxZG0R1XY}J(sf}4|^u1{21f|hVuoixSG*v?DiDDv>q}o7m^*XzDss& zw4dZoSCDFjF%2N5Wt#p3X`DvW-F=PwYWE7sF+Ae!y^!A(EMV zuik?d%aW3+R_LSh zy=^⪻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 L`gh{~8zk^w&KF^% diff --git a/org.simantics.pythonlink.win32.x86_64/src/sclpy.c b/org.simantics.pythonlink.win32.x86_64/src/sclpy.c index b10b36f..1cc36d8 100644 --- a/org.simantics.pythonlink.win32.x86_64/src/sclpy.c +++ b/org.simantics.pythonlink.win32.x86_64/src/sclpy.c @@ -1,1288 +1,1293 @@ -/////////////////////////////////////////////////////// -// // -// 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 - -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 initCalled = 0; -int hasNumpy = 0; - -JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContextImpl(JNIEnv *env, jobject thisObj) { - char name[16]; - - if (!initCalled) { - Py_Initialize(); - initCalled = 1; - - hasNumpy = _import_array(); - hasNumpy = hasNumpy != -1; - } - - sprintf(name, "SCL_%d", ++moduleCount); - - { - PyObject *module = PyModule_New(name); - PyObject *main = PyImport_AddModule("__main__"); - - PyDict_Merge(PyModule_GetDict(module), PyModule_GetDict(main), 0); - - return (jlong)module; - } -} - -JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_deleteContextImpl(JNIEnv *env, jobject thisObj, jlong contextID) { - PyObject *module = (PyObject*)contextID; - Py_XDECREF(module); -} - -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, "", "([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, "", "(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); - - 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"); - } - } - } - - (*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 -} +/////////////////////////////////////////////////////// +// // +// 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 + +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, "", "([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, "", "(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 +} -- 2.45.2