]> gerrit.simantics Code Review - simantics/python.git/blobdiff - org.simantics.pythonlink.win32.x86_64/src/sclpy.c
Print exception type name if we can't get a traceback.
[simantics/python.git] / org.simantics.pythonlink.win32.x86_64 / src / sclpy.c
index 1cc36d8e98ff4552c66eb9113f72570692375026..8e41834ee1d2c505bc0a8e4764782e4c08323503 100644 (file)
@@ -785,97 +785,39 @@ jobject pythonDictionaryAsMap(JNIEnv *env, PyObject *dict) {
        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);
-}
+#define DEF_SETTER(typename, jtype, j2py)                               \
+    JNIEXPORT void JNICALL                                              \
+    Java_org_simantics_pythonlink_PythonContext_setPython##typename     \
+    ##VariableImpl(                                                     \
+        JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, \
+        jtype value) {                                                  \
+            PyObject *module = (PyObject*)contextID;                    \
+                                                                        \
+            PyEval_RestoreThread(main_ts);                              \
+            setPythonVariable(module, getPythonString(env, variableName), \
+                              j2py(env, value));                        \
+            PyEval_SaveThread();                                        \
+    }
 
-JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value) {
+#define getPythonBoolean(env, value) getPythonBool(value)
+#define getPythonLong(env, value) PyLong_FromLongLong(value)
+#define getPythonDouble(env, value) PyFloat_FromDouble(value)
+
+DEF_SETTER(Boolean, jboolean, getPythonBoolean)
+DEF_SETTER(BooleanArray, jbooleanArray, getPythonBooleanList)
+DEF_SETTER(Long, jlong, getPythonLong)
+DEF_SETTER(IntegerArray, jintArray, getPythonIntegerList)
+DEF_SETTER(LongArray, jlongArray, getPythonLongList)
+DEF_SETTER(Double, jdouble, getPythonDouble)
+DEF_SETTER(FloatArray, jfloatArray, getPythonFloatList)
+DEF_SETTER(DoubleArray, jdoubleArray, getPythonDoubleList)
+DEF_SETTER(String, jstring, getPythonString)
+DEF_SETTER(StringArray, jobjectArray, getPythonStringList)
+
+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) {
@@ -883,24 +825,31 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDAr
                return;
        }
 
+       PyEval_RestoreThread(main_ts);
        {
                PyObject *pythonName = getPythonString(env, variableName);
                PyObject *val = getPythonNDArray(env, value);
 
                setPythonVariable(module, pythonName, val);
        }
+       PyEval_SaveThread();
 }
 
-JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonVariantVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value, jobject binding) {
+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);
+       PyEval_RestoreThread(main_ts);
+       setPythonVariable(module, getPythonString(env, variableName),
+                                         getPythonObject(env, value, binding));
+       PyEval_SaveThread();
 }
 
-JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePythonStatementImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring statement) {
+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);
@@ -937,7 +886,11 @@ JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePython
                                                                Py_DECREF(message);
                                                        }
                                                        else {
-                                                               throwPythonException(env, "Internal error, no message");
+                                                               PyTypeObject
+                                                                       *ty = (PyTypeObject *)exceptionType;
+                                                               throwPythonException(
+                                                                               env, ty ? ty->tp_name
+                                                                                               : "Internal error, null exception type");
                                                        }
                                                        Py_DECREF(args);
                                                        Py_DECREF(formatExc);
@@ -951,6 +904,9 @@ JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePython
                                                throwPythonException(env, "Internal error, no traceback module");
                                        }
                                }
+                               Py_XDECREF(exceptionType);
+                               Py_XDECREF(exception);
+                               Py_XDECREF(traceback);
                        }
 
                        PyEval_SaveThread();
@@ -961,269 +917,101 @@ JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePython
        }
 }
 
-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;
-       }
+// Returns a borrowed reference.
+static PyObject *getPythonValue(
+               JNIEnv *env, jlong contextID, jstring variableName) {
+    PyObject *module = (PyObject*)contextID;
+    PyObject *pythonName = getPythonString(env, variableName);
+    PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
 
-       {
-               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;
-       }
-}
+    Py_DECREF(pythonName);
+    if (value == NULL) {
+        throwPythonException(env, "Python variable not found");
+    }
+    return value;
+}
+
+#define DEF_GETTER(typename, jtype, check, desc, py2j)                  \
+    JNIEXPORT jtype JNICALL                                             \
+    Java_org_simantics_pythonlink_PythonContext_getPython##typename     \
+    ##VariableImpl(                                                     \
+            JNIEnv *env, jobject thisObj, jlong contextID,              \
+            jstring variableName) {                                     \
+        jtype result = 0;                                               \
+        PyEval_RestoreThread(main_ts);                                  \
+        do {                                                            \
+            PyObject *value = getPythonValue(env, contextID, variableName); \
+            if (value == 0) break;                                      \
+            if (check(value)) {                                         \
+                result = py2j(env, value);                              \
+            } else {                                                    \
+                throwPythonException(env, "Python variable not " desc); \
+            }                                                           \
+        } while (0);                                                    \
+        PyEval_SaveThread();                                            \
+        return result;                                                  \
+    }
 
-JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
-       PyObject *module = (PyObject*)contextID;
+#define pythonBoolAsJboolean(env, value) ((value) == Py_True)
+#define pythonLongAsJlong(env, value) PyLong_AsLongLong(value)
+#define pythonFloatAsJdouble(env, value) PyFloat_AsDouble(value)
+
+DEF_GETTER(String, jstring, PyUnicode_Check, "a string",
+                  pythonStringAsJavaString)
+DEF_GETTER(StringArray, jobjectArray, PySequence_Check, "a sequence",
+                  pythonSequenceAsStringArray)
+DEF_GETTER(Boolean, jboolean, PyBool_Check, "a Boolean", pythonBoolAsJboolean)
+DEF_GETTER(BooleanArray, jbooleanArray, PySequence_Check, "a sequence",
+                  pythonSequenceAsBooleanArray)
+DEF_GETTER(Long, jlong, PyLong_Check, "an integer", pythonLongAsJlong)
+DEF_GETTER(IntegerArray, jintArray, PySequence_Check, "a sequence",
+                  pythonSequenceAsIntegerArray)
+DEF_GETTER(LongArray, jlongArray, PySequence_Check, "a sequence",
+                  pythonSequenceAsLongArray)
+DEF_GETTER(Double, jdouble, PyFloat_Check, "a float", pythonFloatAsJdouble)
+DEF_GETTER(DoubleArray, jdoubleArray, PySequence_Check, "a sequence",
+                  pythonSequenceAsDoubleArray)
+
+JNIEXPORT jobject JNICALL
+Java_org_simantics_pythonlink_PythonContext_getPythonNDArrayVariableImpl(
+               JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+       jobject result = NULL;
 
        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;
-               }
-
+       PyEval_RestoreThread(main_ts);
+       do {
+               PyObject *value = getPythonValue(env, contextID, variableName);
+               if (value == NULL) break;
                if (!PyArray_Check(value)) {
                        throwPythonException(env, "Python variable not an ndarray");
-                       return NULL;
+               } else if (PyArray_TYPE((PyArrayObject*)value) != NPY_DOUBLE) {
+                       throwPythonException(
+                                       env, "Only ndarrays of type double are supported");
+               } else {
+                       result = pythonArrayAsNDArray(env, (PyArrayObject *)value);
                }
-
-               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;
-       }
+       } while (0);
+       PyEval_SaveThread();
+       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);
+#define python_anything_goes(value) 1
 
-       if (!PyDict_Contains(dict, pythonName)) {
-               return 0;
-       }
+DEF_GETTER(Variant, jobject, python_anything_goes, "frabjous",
+                  pythonObjectAsObject)
 
+JNIEXPORT jint JNICALL
+Java_org_simantics_pythonlink_PythonContext_getPythonVariableTypeImpl(
+               JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
+       jint result = 0;
+       PyEval_RestoreThread(main_ts);
        {
-               PyObject *value = PyDict_GetItem(dict, pythonName);
-
-               jint result;
-
+               PyObject *value = getPythonValue(env, contextID, variableName);
                if (PyBool_Check(value))
                        result = 1;
                else if (PyLong_Check(value))
@@ -1242,28 +1030,36 @@ JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVari
                        result = 8;
                else
                        result = -1;
-
-               return result;
        }
+       PyEval_SaveThread();
+       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);
+JNIEXPORT jobjectArray JNICALL
+Java_org_simantics_pythonlink_PythonContext_getPythonVariableNamesImpl(
+               JNIEnv *env, jobject thisObj, jlong contextID) {
+       jobjectArray result = NULL;
+       PyEval_RestoreThread(main_ts);
+       {
+               PyObject *module = (PyObject*)contextID;
+               PyObject *dict = PyModule_GetDict(module);
 
-       jobjectArray result = (*env)->NewObjectArray(env, (jsize)size, (*env)->FindClass(env, STRING_CLASS), NULL);
+               PyObject *keys = PyDict_Keys(dict);
+               Py_ssize_t size = PyList_Size(keys);
+               Py_ssize_t i;
 
-       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);
-       }
+               result = (*env)->NewObjectArray(
+                               env, (jsize)size, (*env)->FindClass(env, STRING_CLASS), NULL);
 
-       Py_XDECREF(keys);
+               for (i = 0; i < size; i++) {
+                       jstring javaName = pythonStringAsJavaString(
+                                       env, PyList_GetItem(keys, i));
+                       (*env)->SetObjectArrayElement(env, result, (jint)i, javaName);
+               }
 
+               Py_XDECREF(keys);
+       }
+       PyEval_SaveThread();
        return result;
 }