]> gerrit.simantics Code Review - simantics/python.git/commitdiff
Python tweaks
authorReino Ruusu <reino.ruusu@vtt.fi>
Wed, 25 Jan 2017 16:51:02 +0000 (18:51 +0200)
committerReino Ruusu <reino.ruusu@vtt.fi>
Wed, 25 Jan 2017 16:51:02 +0000 (18:51 +0200)
- Changed the way context modules are created
- Allow Python to produce SCL console output

Change-Id: I41e8b876d55db8815959ebc90487c3e481f4604b

org.simantics.pythonlink.win32.x86_64/jnipython.dll
org.simantics.pythonlink.win32.x86_64/src/sclpy.c
org.simantics.pythonlink.win32.x86_64/src/sclpy.h
org.simantics.pythonlink/src/org/simantics/pythonlink/PythonContext.java

index 7fff774adac1bb1b1d2c5ffbffa6043e44d877e1..1770fb739bc91fd7193ea478c320ecd35812dbe6 100644 (file)
Binary files a/org.simantics.pythonlink.win32.x86_64/jnipython.dll and b/org.simantics.pythonlink.win32.x86_64/jnipython.dll differ
index b10b36f5d3c1103aeda3c6e7582ff44bdb6670b5..a6c64abf183e2b68b3a9ab48e54bccbd26172723 100644 (file)
@@ -32,10 +32,48 @@ jint throwIllegalArgumentException( JNIEnv *env, char *message ) {
        return throwException( env, ILLEGAL_ARGUMENT_EXCEPTION, message );\r
 }\r
 \r
+PyObject* getModule(jlong contextID) {\r
+       return PyState_FindModule((PyModuleDef*) contextID);\r
+//     return PyImport_AddModule("__main__");\r
+}\r
+\r
 int moduleCount = 0;\r
 int initCalled = 0;\r
 int hasNumpy = 0;\r
 \r
+static JNIEnv *currentEnv = NULL;\r
+jobject sclWriter = NULL;\r
+\r
+static PyObject *\r
+writeToSCL(PyObject *self, PyObject *args)\r
+{\r
+    if (currentEnv != NULL && sclWriter != NULL) {\r
+       JNIEnv *env = currentEnv;\r
+\r
+               Py_UNICODE *what;\r
+               Py_ssize_t length;\r
+               if (!PyArg_ParseTuple(args, "u#", &what, &length))\r
+                       return NULL;\r
+\r
+               {\r
+               jclass writerClass = (*env)->FindClass(env, WRITER_CLASS);\r
+               jmethodID writeMethod = (*env)->GetMethodID(env, writerClass, "write", "([CII)V");\r
+               jcharArray chars = (*env)->NewCharArray(env, (jsize)length);\r
+\r
+               (*env)->SetCharArrayRegion(env, chars, 0, length, what);\r
+               (*env)->CallVoidMethod(env, sclWriter, writeMethod, chars, 0, length);\r
+               }\r
+    }\r
+\r
+    return Py_BuildValue("");\r
+}\r
+\r
+static PyMethodDef sclWriterMethods[] = {\r
+    {"write", writeToSCL, METH_VARARGS, "Write something."},\r
+    {NULL, NULL, 0, NULL}\r
+};\r
+\r
+\r
 JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContextImpl(JNIEnv *env, jobject thisObj) {\r
        char name[16];\r
 \r
@@ -43,6 +81,15 @@ JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContex
         Py_Initialize();\r
         initCalled = 1;\r
 \r
+        {\r
+               static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "sclwriter", NULL, -1, sclWriterMethods, };\r
+                       PyObject *m = PyModule_Create(&moduledef);\r
+\r
+               if (m == NULL) throwException(env, PYTHON_EXCEPTION, "Failed to create SCL writer module");\r
+                       PySys_SetObject("stdout", m);\r
+                       PySys_SetObject("stderr", m);\r
+        }\r
+\r
        hasNumpy = _import_array();\r
        hasNumpy = hasNumpy != -1;\r
        }\r
@@ -50,18 +97,35 @@ JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContex
        sprintf(name, "SCL_%d", ++moduleCount);\r
 \r
        {\r
-               PyObject *module = PyModule_New(name);\r
-               PyObject *main = PyImport_AddModule("__main__");\r
+               PyObject *module;\r
+               PyModuleDef *modDef = malloc(sizeof(PyModuleDef));\r
+               memset(modDef, 0, sizeof(PyModuleDef));\r
+               modDef->m_name = strdup(name);\r
+               modDef->m_doc = NULL;\r
+               modDef->m_size = -1;\r
 \r
-               PyDict_Merge(PyModule_GetDict(module), PyModule_GetDict(main), 0);\r
+               module = PyModule_Create(modDef);\r
+               Py_INCREF(module);\r
+               PyState_AddModule(module, modDef);\r
 \r
-               return (jlong)module;\r
+               {\r
+                       PyObject *builtin = PyImport_AddModule("builtins");\r
+                       PyObject *dict = PyModule_GetDict(module);\r
+                       PyDict_SetItemString(dict, "__builtin__", builtin);\r
+                       PyDict_SetItemString(dict, "__builtins__", builtin);\r
+\r
+                       return (jlong)modDef;\r
+               }\r
        }\r
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_deleteContextImpl(JNIEnv *env, jobject thisObj, jlong contextID) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyModuleDef *modDef = (PyModuleDef*)contextID;\r
+       PyObject *module = PyState_FindModule(modDef);\r
        Py_XDECREF(module);\r
+       PyState_RemoveModule(modDef);\r
+       free((char*)modDef->m_name);\r
+       free(modDef);\r
 }\r
 \r
 PyObject *getPythonBool(jboolean value) {\r
@@ -783,7 +847,7 @@ jobject pythonDictionaryAsMap(JNIEnv *env, PyObject *dict) {
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBooleanVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jboolean value) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
        PyObject *val = getPythonBool(value);\r
@@ -792,7 +856,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBool
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBooleanArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jbooleanArray value) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
        PyObject *val = getPythonBooleanList(env, value);\r
@@ -801,7 +865,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBool
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonLongVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jlong value) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
        PyObject *val = PyLong_FromLongLong(value);\r
@@ -810,7 +874,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonLong
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jintArray value) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
        PyObject *val = getPythonIntegerList(env, value);\r
@@ -819,7 +883,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonInte
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonLongArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jlongArray value) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
        PyObject *val = getPythonLongList(env, value);\r
@@ -828,7 +892,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonLong
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdouble value) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
        PyObject *val = PyFloat_FromDouble(value);\r
@@ -837,7 +901,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoub
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonFloatArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jfloatArray value) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
        PyObject *val = getPythonFloatList(env, value);\r
@@ -846,7 +910,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonFloa
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdoubleArray value) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
        PyObject *val = getPythonDoubleList(env, value);\r
@@ -855,7 +919,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoub
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jstring value) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
        PyObject *val = getPythonString(env, value);\r
@@ -864,7 +928,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStri
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobjectArray value) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
        PyObject *val = getPythonStringList(env, value);\r
@@ -873,7 +937,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStri
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        if (!hasNumpy) {\r
                throwPythonException(env, "Importing numpy failed");\r
@@ -889,7 +953,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDAr
 }\r
 \r
 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonVariantVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value, jobject binding) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
        PyObject *val = getPythonObject(env, value, binding);\r
@@ -898,16 +962,26 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonVari
 }\r
 \r
 JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePythonStatementImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring statement) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        const char *utfchars = (*env)->GetStringUTFChars(env, statement, NULL);\r
 \r
        PyErr_Clear();\r
        {\r
+               jclass sclReportingWriterClass = (*env)->FindClass(env, SCL_REPORTING_WRITER_CLASS);\r
+               jmethodID constructor = (*env)->GetMethodID(env, sclReportingWriterClass, "<init>", "()V");\r
+               jmethodID flushMethod = (*env)->GetMethodID(env, sclReportingWriterClass, "flush", "()V");\r
+\r
                PyObject *globals;\r
 \r
                globals = PyModule_GetDict(module);\r
 \r
+               currentEnv = env;\r
+               if (sclReportingWriterClass && constructor)\r
+                       sclWriter = (*env)->NewObject(env, sclReportingWriterClass, constructor);\r
+               else\r
+                       sclWriter = NULL;\r
+\r
                {\r
                        PyObject *result = PyRun_String(utfchars, Py_file_input, globals, globals);\r
 \r
@@ -951,13 +1025,20 @@ JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePython
 \r
                        (*env)->ReleaseStringUTFChars(env, statement, utfchars);\r
 \r
+                       if (sclWriter != NULL) {\r
+                               (*env)->CallVoidMethod(env, sclWriter, flushMethod);\r
+                       }\r
+\r
+                       currentEnv = NULL;\r
+                       sclWriter = NULL;\r
+\r
                        return result != NULL ? 0 : 1;\r
                }\r
        }\r
 }\r
 \r
 JNIEXPORT jstring JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
 \r
@@ -979,7 +1060,7 @@ JNIEXPORT jstring JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonS
 }\r
 \r
 JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
 \r
@@ -1001,7 +1082,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPy
 }\r
 \r
 JNIEXPORT jboolean JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonBooleanVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
 \r
@@ -1020,7 +1101,7 @@ JNIEXPORT jboolean JNICALL Java_org_simantics_pythonlink_PythonContext_getPython
 }\r
 \r
 JNIEXPORT jbooleanArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonBooleanArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
 \r
@@ -1042,7 +1123,7 @@ JNIEXPORT jbooleanArray JNICALL Java_org_simantics_pythonlink_PythonContext_getP
 }\r
 \r
 JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLongVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
 \r
@@ -1064,7 +1145,7 @@ JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLon
 }\r
 \r
 JNIEXPORT jintArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
 \r
@@ -1086,7 +1167,7 @@ JNIEXPORT jintArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPytho
 }\r
 \r
 JNIEXPORT jlongArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLongArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
 \r
@@ -1108,7 +1189,7 @@ JNIEXPORT jlongArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPyth
 }\r
 \r
 JNIEXPORT jdouble JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
 \r
@@ -1130,7 +1211,7 @@ JNIEXPORT jdouble JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonD
 }\r
 \r
 JNIEXPORT jdoubleArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
 \r
@@ -1152,7 +1233,7 @@ JNIEXPORT jdoubleArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPy
 }\r
 \r
 JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        if (!hasNumpy) {\r
                throwPythonException(env, "Importing numpy failed");\r
@@ -1186,7 +1267,7 @@ JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonN
 }\r
 \r
 JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariantVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
 \r
@@ -1205,7 +1286,7 @@ JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonV
 }\r
 \r
 JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariableTypeImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
        PyObject *dict = PyModule_GetDict(module);\r
 \r
        PyObject *pythonName = getPythonString(env, variableName);\r
@@ -1243,7 +1324,7 @@ JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVari
 }\r
 \r
 JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariableNamesImpl(JNIEnv *env, jobject thisObj, jlong contextID) {\r
-       PyObject *module = (PyObject*)contextID;\r
+       PyObject *module = getModule(contextID);\r
        PyObject *dict = PyModule_GetDict(module);\r
 \r
        PyObject *keys = PyDict_Keys(dict);\r
index 4032d4854512fb27fa18008e6a1c23b894140e63..15d681d43b7c5e023fccc34604c79ce997bd29d2 100644 (file)
@@ -34,6 +34,9 @@
 #define MAP_CLASS "java/util/Map"\r
 #define SET_CLASS "java/util/Set"\r
 \r
+#define WRITER_CLASS "java/io/Writer"\r
+#define SCL_REPORTING_WRITER_CLASS "org/simantics/scl/runtime/reporting/SCLReportingWriter"\r
+\r
 #define PACKAGE_PREFIX "org/simantics/pythonlink/"\r
 \r
 #define NDARRAY_CLASS (PACKAGE_PREFIX "NDArray")\r
index 6c96dd3bde8a877e1e2115c4f1686f4101a44200..2063c0bd7b53ecfcd113b2e7a5185a1bf42e1714 100644 (file)
@@ -13,6 +13,8 @@ import org.simantics.databoard.Bindings;
 import org.simantics.databoard.binding.Binding;\r
 import org.simantics.databoard.binding.error.BindingException;\r
 import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.scl.runtime.SCLContext;\r
+import org.simantics.scl.runtime.reporting.SCLReportingHandler;\r
 \r
 public class PythonContext implements Closeable {\r
     private long contextID;\r
@@ -75,7 +77,14 @@ public class PythonContext implements Closeable {
     }\r
     \r
     public void executePythonStatement(String statement) {\r
-        execute(() -> executePythonStatementImpl( contextID, statement ));\r
+       SCLContext sclContext = SCLContext.getCurrent();\r
+       \r
+        execute(() -> {\r
+               SCLContext.push(sclContext);\r
+               executePythonStatementImpl( contextID, statement );\r
+               SCLContext.pop();\r
+        });\r
+        \r
        for (Listener l : listeners) { l.updated(null); }\r
     }\r
 \r