]> gerrit.simantics Code Review - simantics/python.git/blobdiff - org.simantics.pythonlink.win32.x86_64/src/sclpy.c
Use the executor for all Python C API calls.
[simantics/python.git] / org.simantics.pythonlink.win32.x86_64 / src / sclpy.c
index 0db1e388c792b1909059d03895f1f77a8bea8e66..b10b36f5d3c1103aeda3c6e7582ff44bdb6670b5 100644 (file)
@@ -24,6 +24,10 @@ jint throwException( JNIEnv *env, char *className, char *message )
     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
@@ -442,6 +446,9 @@ PyObject *getPythonObject(JNIEnv *env, jobject value, jobject binding) {
        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
@@ -578,7 +585,7 @@ jobjectArray pythonSequenceAsStringArray(JNIEnv *env, PyObject *seq) {
                        (*env)->SetObjectArrayElement(env, array, i, value);\r
                }\r
                else {\r
-                       throwException(env, RUNTIME_EXCEPTION, "List item not a string");\r
+                       throwPythonException(env, "List item not a string");\r
                        return NULL;\r
                }\r
        }\r
@@ -600,7 +607,7 @@ jdoubleArray pythonSequenceAsDoubleArray(JNIEnv *env, PyObject *seq) {
                        (*env)->SetDoubleArrayRegion(env, array, i, 1, &value);\r
                }\r
                else {\r
-                       throwException(env, RUNTIME_EXCEPTION, "List item not a floating point value");\r
+                       throwPythonException(env, "List item not a floating point value");\r
                        return NULL;\r
                }\r
        }\r
@@ -659,7 +666,7 @@ jbooleanArray pythonSequenceAsBooleanArray(JNIEnv *env, PyObject *seq) {
                        (*env)->SetBooleanArrayRegion(env, array, i, 1, &value);\r
                }\r
                else {\r
-                       throwException(env, RUNTIME_EXCEPTION, "List item not a boolean");\r
+                       throwPythonException(env, "List item not a boolean");\r
                        return NULL;\r
                }\r
        }\r
@@ -681,7 +688,7 @@ jintArray pythonSequenceAsIntegerArray(JNIEnv *env, PyObject *seq) {
                        (*env)->SetIntArrayRegion(env, array, i, 1, &value);\r
                }\r
                else {\r
-                       throwException(env, RUNTIME_EXCEPTION, "List item not an integer");\r
+                       throwPythonException(env, "List item not an integer");\r
                        return NULL;\r
                }\r
        }\r
@@ -703,7 +710,7 @@ jlongArray pythonSequenceAsLongArray(JNIEnv *env, PyObject *seq) {
                        (*env)->SetLongArrayRegion(env, array, i, 1, &value);\r
                }\r
                else {\r
-                       throwException(env, RUNTIME_EXCEPTION, "List item not an integer");\r
+                       throwPythonException(env, "List item not an integer");\r
                        return NULL;\r
                }\r
        }\r
@@ -726,7 +733,7 @@ jobject pythonArrayAsNDArray(JNIEnv *env, PyArrayObject *array) {
        int i;\r
 \r
        if (len > JAVA_MAXINT) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Array too large");\r
+               throwPythonException(env, "Array too large");\r
                return NULL;\r
        }\r
 \r
@@ -869,7 +876,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDAr
        PyObject *module = (PyObject*)contextID;\r
 \r
        if (!hasNumpy) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed");\r
+               throwPythonException(env, "Importing numpy failed");\r
                return;\r
        }\r
 \r
@@ -906,11 +913,40 @@ JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePython
 \r
                        PyObject *exceptionType = PyErr_Occurred();\r
                        if (exceptionType != NULL) {\r
-                               PyObject *exception, *stackTrace;\r
-                               char *message;\r
-                               PyErr_Fetch(&exceptionType, &exception, &stackTrace);\r
-                               message = PyUnicode_AsUTF8(exception);\r
-                               throwException(env, RUNTIME_EXCEPTION, message);\r
+                               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
@@ -927,12 +963,12 @@ JNIEXPORT jstring JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonS
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0;\r
        }\r
 \r
        if (!PyUnicode_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a string");\r
+               throwPythonException(env, "Python variable not a string");\r
                return 0;\r
        }\r
 \r
@@ -949,12 +985,12 @@ JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPy
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0;\r
        }\r
 \r
        if (!PySequence_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
+               throwPythonException(env, "Python variable not a sequence");\r
                return 0;\r
        }\r
 \r
@@ -971,12 +1007,12 @@ JNIEXPORT jboolean JNICALL Java_org_simantics_pythonlink_PythonContext_getPython
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0;\r
        }\r
 \r
        if (!PyBool_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a boolean");\r
+               throwPythonException(env, "Python variable not a boolean");\r
                return 0;\r
        }\r
 \r
@@ -990,12 +1026,12 @@ JNIEXPORT jbooleanArray JNICALL Java_org_simantics_pythonlink_PythonContext_getP
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0;\r
        }\r
 \r
        if (!PySequence_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
+               throwPythonException(env, "Python variable not a sequence");\r
                return 0;\r
        }\r
 \r
@@ -1012,12 +1048,12 @@ JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLon
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0;\r
        }\r
 \r
        if (!PyLong_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not an integer");\r
+               throwPythonException(env, "Python variable not an integer");\r
                return 0;\r
        }\r
 \r
@@ -1034,12 +1070,12 @@ JNIEXPORT jintArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPytho
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return NULL;\r
        }\r
 \r
        if (!PySequence_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
+               throwPythonException(env, "Python variable not a sequence");\r
                return NULL;\r
        }\r
 \r
@@ -1056,12 +1092,12 @@ JNIEXPORT jlongArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPyth
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return NULL;\r
        }\r
 \r
        if (!PySequence_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
+               throwPythonException(env, "Python variable not a sequence");\r
                return NULL;\r
        }\r
 \r
@@ -1078,12 +1114,12 @@ JNIEXPORT jdouble JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonD
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0.0;\r
        }\r
 \r
        if (!PyFloat_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a float");\r
+               throwPythonException(env, "Python variable not a float");\r
                return 0.0;\r
        }\r
 \r
@@ -1100,12 +1136,12 @@ JNIEXPORT jdoubleArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPy
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return NULL;\r
        }\r
 \r
        if (!PySequence_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
+               throwPythonException(env, "Python variable not a sequence");\r
                return NULL;\r
        }\r
 \r
@@ -1119,7 +1155,7 @@ JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonN
        PyObject *module = (PyObject*)contextID;\r
 \r
        if (!hasNumpy) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed");\r
+               throwPythonException(env, "Importing numpy failed");\r
                return NULL;\r
        }\r
 \r
@@ -1128,17 +1164,17 @@ JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonN
 \r
                PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
                if (value == NULL) {\r
-                       throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+                       throwPythonException(env, "Python variable not found");\r
                        return NULL;\r
                }\r
 \r
                if (!PyArray_Check(value)) {\r
-                       throwException(env, RUNTIME_EXCEPTION, "Python variable not an ndarray");\r
+                       throwPythonException(env, "Python variable not an ndarray");\r
                        return NULL;\r
                }\r
 \r
                if (PyArray_TYPE((PyArrayObject*)value) != NPY_DOUBLE) {\r
-                       throwException(env, RUNTIME_EXCEPTION, "Only ndarrays of type double are supported");\r
+                       throwPythonException(env, "Only ndarrays of type double are supported");\r
                        return NULL;\r
                }\r
 \r
@@ -1156,7 +1192,7 @@ JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonV
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return NULL;\r
        }\r
 \r