return throwException( env, ILLEGAL_ARGUMENT_EXCEPTION, message );
}
+// Returns a borrowed reference.
PyObject* getModule(jlong contextID) {
return PyState_FindModule((PyModuleDef*) contextID);
// return PyImport_AddModule("__main__");
writeToSCL(PyObject *self, PyObject *args)
{
if (currentEnv != NULL && sclWriter != NULL) {
- JNIEnv *env = currentEnv;
-
Py_UNICODE *what;
Py_ssize_t length;
+ JNIEnv *env = currentEnv;
+
if (!PyArg_ParseTuple(args, "u#", &what, &length))
- return Py_BuildValue("");
+ Py_RETURN_NONE;
{
- jclass writerClass = (*env)->FindClass(env, WRITER_CLASS);
- jmethodID writeMethod = (*env)->GetMethodID(env, writerClass, "write", "([CII)V");
- jcharArray chars = (*env)->NewCharArray(env, (jsize)length);
-
- (*env)->SetCharArrayRegion(env, chars, 0, length, what);
- (*env)->CallVoidMethod(env, sclWriter, writeMethod, chars, 0, length);
+ PyThreadState *my_ts = PyThreadState_Get();
+ if (my_ts == main_ts) {
+ jclass writerClass = (*env)->FindClass(env, WRITER_CLASS);
+ jmethodID writeMethod = (*env)->GetMethodID(env, writerClass, "write", "([CII)V");
+ jcharArray chars = (*env)->NewCharArray(env, (jsize)length);
+
+ (*env)->SetCharArrayRegion(env, chars, 0, length, what);
+ Py_BEGIN_ALLOW_THREADS
+ (*env)->CallVoidMethod(env, sclWriter, writeMethod, chars, 0, length);
+ Py_END_ALLOW_THREADS
+ } else {
+ //TODO
+ }
}
}
- return Py_BuildValue("");
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+flushSCL(PyObject *self, PyObject *args)
+{
+ if (currentEnv != NULL && sclWriter != NULL) {
+ JNIEnv *env = currentEnv;
+ PyThreadState *my_ts = PyThreadState_Get();
+ if (my_ts != main_ts) {
+ // TODO: Process calls from other threads
+ Py_RETURN_NONE;
+ }
+
+ {
+ jclass writerClass = (*env)->FindClass(env, WRITER_CLASS);
+ jmethodID flushMethod = (*env)->GetMethodID(env, writerClass, "flush", "()V");
+
+ Py_BEGIN_ALLOW_THREADS
+ (*env)->CallVoidMethod(env, sclWriter, flushMethod);
+ Py_END_ALLOW_THREADS
+ }
+ }
+
+ Py_RETURN_NONE;
}
static PyMethodDef sclWriterMethods[] = {
{"write", writeToSCL, METH_VARARGS, "Write something."},
+ {"flush", flushSCL, METH_VARARGS, "Flush output."},
{NULL, NULL, 0, NULL}
};
+JNIEXPORT void JNICALL
+Java_org_simantics_pythonlink_PythonContext_initializePython(
+ JNIEnv *env, jobject thisObj, jobject writer) {
+ Py_Initialize();
-JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContextImpl(JNIEnv *env, jobject thisObj) {
- char name[16];
+ {
+ static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT, "sclwriter", NULL, -1, sclWriterMethods
+ };
+ PyObject *m = PyModule_Create(&moduledef);
+
+ sclWriter = (*env)->NewGlobalRef(env, writer);
+
+ if (m == NULL) {
+ throwException(env, PYTHON_EXCEPTION,
+ "Failed to create SCL writer module");
+ } else {
+ PySys_SetObject("stdout", m);
+ PySys_SetObject("stderr", m);
+ Py_DECREF(m);
+ }
+ }
- if (!main_ts) {
- Py_Initialize();
+ hasNumpy = _import_array();
+ hasNumpy = hasNumpy != -1;
- {
- static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "sclwriter", NULL, -1, sclWriterMethods, };
- PyObject *m = PyModule_Create(&moduledef);
+ main_ts = PyEval_SaveThread();
+}
- if (m == NULL) throwException(env, PYTHON_EXCEPTION, "Failed to create SCL writer module");
- PySys_SetObject("stdout", m);
- PySys_SetObject("stderr", m);
- }
+JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContextImpl(JNIEnv *env, jobject thisObj) {
+ char name[16];
- hasNumpy = _import_array();
- hasNumpy = hasNumpy != -1;
- main_ts = PyEval_SaveThread();
+ if (!main_ts) {
+ return 0;
}
sprintf(name, "SCL_%d", ++moduleCount);
modDef->m_size = -1;
module = PyModule_Create(modDef);
- Py_INCREF(module);
PyState_AddModule(module, modDef);
-
{
PyObject *builtin = PyImport_AddModule("builtins");
PyObject *dict = PyModule_GetDict(module);
+ Py_DECREF(module);
PyDict_SetItemString(dict, "__builtin__", builtin);
PyDict_SetItemString(dict, "__builtins__", builtin);
}
}
-JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_deleteContextImpl(JNIEnv *env, jobject thisObj, jlong contextID) {
+JNIEXPORT void JNICALL
+Java_org_simantics_pythonlink_PythonContext_deleteContextImpl(
+ JNIEnv *env, jobject thisObj, jlong contextID) {
PyModuleDef *modDef = (PyModuleDef*)contextID;
- PyObject *module;
PyEval_RestoreThread(main_ts);
- module = PyState_FindModule(modDef);
- Py_XDECREF(module);
PyState_RemoveModule(modDef);
free((char*)modDef->m_name);
free(modDef);
PyList_SetItem(result, i, getPythonString(env, (jstring)item));
}
else {
+ Py_INCREF(Py_None);
PyList_SetItem(result, i, Py_None);
}
}
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);
+ PyObject
+ *key = getPythonString(env, fieldName),
+ *item = getPythonObject(env, componentObject, componentBinding);
+ PyDict_SetItem(result, key, item);
+ Py_DECREF(key);
+ Py_DECREF(item);
}
return result;
jobject item = (*env)->CallObjectMethod(env, binding, getMethod, object, i);
if (item != NULL)
PyList_SetItem(result, i, getPythonObject(env, item, componentBinding));
- else
+ else {
+ Py_INCREF(Py_None);
PyList_SetItem(result, i, Py_None);
+ }
}
return result;
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));
+ PyObject
+ *pkey = getPythonObject(env, key, keyBinding),
+ *pitem = getPythonObject(env, item, valueBinding);
+ PyDict_SetItem(result, pkey, pitem);
+ Py_DECREF(pkey);
+ Py_DECREF(pitem);
}
(*env)->DeleteLocalRef(env, keys);
}
}
+// Steals refs to name & value.
void setPythonVariable(PyObject *module, PyObject *name, PyObject *value) {
if (name && value) {
PyDict_SetItem(PyModule_GetDict(module), name, value);
PyObject *item = PySequence_GetItem(seq, i);
if (PyUnicode_Check(item)) {
jstring value = pythonStringAsJavaString(env, item);
+ Py_DECREF(item);
(*env)->SetObjectArrayElement(env, array, i, value);
}
else {
+ Py_DECREF(item);
throwPythonException(env, "List item not a string");
return NULL;
}
for (i = 0; i < jlen; i++) {
PyObject *item = PySequence_GetItem(seq, i);
if (PyFloat_Check(item)) {
- double value = PyFloat_AsDouble(item);
+ jdouble value = PyFloat_AsDouble(item);
+ Py_DECREF(item);
(*env)->SetDoubleArrayRegion(env, array, i, 1, &value);
}
else {
+ Py_DECREF(item);
throwPythonException(env, "List item not a floating point value");
return NULL;
}
for (i = 0; i < jlen; i++) {
PyObject *item = PySequence_GetItem(seq, i);
jobject object = pythonObjectAsObject(env, item);
+ Py_DECREF(item);
(*env)->SetObjectArrayElement(env, array, i, object);
}
PyObject *item = PySequence_GetItem(seq, i);
if (PyBool_Check(item)) {
jboolean value = item == Py_True;
+ Py_DECREF(item);
(*env)->SetBooleanArrayRegion(env, array, i, 1, &value);
}
else {
+ Py_DECREF(item);
throwPythonException(env, "List item not a boolean");
return NULL;
}
PyObject *item = PySequence_GetItem(seq, i);
if (PyLong_Check(item)) {
jint value = PyLong_AsLong(item);
+ Py_DECREF(item);
(*env)->SetIntArrayRegion(env, array, i, 1, &value);
}
else {
+ Py_DECREF(item);
throwPythonException(env, "List item not an integer");
return NULL;
}
PyObject *item = PySequence_GetItem(seq, i);
if (PyLong_Check(item)) {
jlong value = PyLong_AsLongLong(item);
+ Py_DECREF(item);
(*env)->SetLongArrayRegion(env, array, i, 1, &value);
}
else {
+ Py_DECREF(item);
throwPythonException(env, "List item not an integer");
return NULL;
}
PyEval_SaveThread();
}
+static PyObject *getExceptionMessage(PyObject *exceptionType, PyObject *exception, PyObject *traceback) {
+ PyObject *formatExc = NULL, *args = NULL;
+ PyObject *tracebackModule = PyImport_ImportModule("traceback");
+ if (!tracebackModule) {
+ return NULL;
+ }
+
+ if (exception && traceback) {
+ formatExc = PyDict_GetItemString(PyModule_GetDict(tracebackModule), "format_exception");
+ args = PyTuple_Pack(3, exceptionType, exception, traceback);
+ }
+ else if (exception) {
+ formatExc = PyDict_GetItemString(PyModule_GetDict(tracebackModule), "format_exception_only");
+ args = PyTuple_Pack(2, exceptionType, exception);
+ }
+
+ Py_DECREF(tracebackModule);
+
+ if (formatExc != NULL && args != NULL) {
+ PyObject *result = PyObject_CallObject(formatExc, args);
+ Py_XDECREF(args);
+ Py_XDECREF(formatExc);
+ return result;
+ }
+ else {
+ Py_XDECREF(args);
+ Py_XDECREF(formatExc);
+ return NULL;
+ }
+}
+
JNIEXPORT jint JNICALL
Java_org_simantics_pythonlink_PythonContext_executePythonStatementImpl(
JNIEnv *env, jobject thisObj, jlong contextID, jstring statement) {
{
PyObject *module = getModule(contextID);
- jclass sclReportingWriterClass = (*env)->FindClass(env, SCL_REPORTING_WRITER_CLASS);
- jmethodID constructor = (*env)->GetMethodID(env, sclReportingWriterClass, "<init>", "()V");
- jmethodID flushMethod = (*env)->GetMethodID(env, sclReportingWriterClass, "flush", "()V");
-
PyObject *globals;
globals = PyModule_GetDict(module);
currentEnv = env;
- if (sclReportingWriterClass && constructor)
- sclWriter = (*env)->NewObject(env, sclReportingWriterClass, constructor);
- else
- sclWriter = NULL;
{
PyObject *result = PyRun_String(utfchars, Py_file_input, globals, globals);
-
PyObject *exceptionType = PyErr_Occurred();
+
if (exceptionType != NULL) {
- PyObject *exception, *traceback;
+ PyObject *exception, *traceback, *message;
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 {
- PyTypeObject
- *ty = (PyTypeObject *)exceptionType;
- throwPythonException(
- env, ty ? ty->tp_name
- : "Internal error, null exception type");
- }
- 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");
- }
+ message = getExceptionMessage(exceptionType, exception, traceback);
+ 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 {
+ PyTypeObject
+ *ty = (PyTypeObject *)exceptionType;
+ throwPythonException(
+ env, ty ? ty->tp_name
+ : "Internal error, null exception type");
}
+
Py_XDECREF(exceptionType);
Py_XDECREF(exception);
Py_XDECREF(traceback);
PyEval_SaveThread();
(*env)->ReleaseStringUTFChars(env, statement, utfchars);
- if (sclWriter != NULL) {
- (*env)->CallVoidMethod(env, sclWriter, flushMethod);
- }
-
currentEnv = NULL;
- sclWriter = NULL;
return result != NULL ? 0 : 1;
}
// Returns a borrowed reference.
static PyObject *getPythonValue(
JNIEnv *env, jlong contextID, jstring variableName) {
- PyObject *module = getModule(contextID);
+ PyObject *module = getModule(contextID);
PyObject *pythonName = getPythonString(env, variableName);
PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);