1 ///////////////////////////////////////////////////////
3 // VTT Technical Research Centre of Finland LTD //
4 // For internal use only. Do not redistribute. //
7 // Antton Tapani ext-antton.tapani@vtt.fi //
9 // Last modified by Antton Tapani 9.2016 //
11 ///////////////////////////////////////////////////////
17 jint throwException( JNIEnv *env, char *className, char *message )
19 jclass exClass = (*env)->FindClass( env, className);
20 if (exClass == NULL) {
24 return (*env)->ThrowNew( env, exClass, message );
27 jint throwPythonException( JNIEnv *env, char *message ) {
28 return throwException( env, PYTHON_EXCEPTION, message );
31 jint throwIllegalArgumentException( JNIEnv *env, char *message ) {
32 return throwException( env, ILLEGAL_ARGUMENT_EXCEPTION, message );
37 PyThreadState *main_ts = 0;
39 JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContextImpl(JNIEnv *env, jobject thisObj) {
45 hasNumpy = _import_array();
46 hasNumpy = hasNumpy != -1;
47 main_ts = PyEval_SaveThread();
50 sprintf(name, "SCL_%d", ++moduleCount);
52 PyEval_RestoreThread(main_ts);
54 PyObject *module = PyModule_New(name);
55 PyObject *main = PyImport_AddModule("__main__");
57 PyDict_Merge(PyModule_GetDict(module), PyModule_GetDict(main), 0);
63 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_deleteContextImpl(JNIEnv *env, jobject thisObj, jlong contextID) {
64 PyObject *module = (PyObject*)contextID;
65 PyEval_RestoreThread(main_ts);
70 PyObject *getPythonBool(jboolean value) {
79 PyObject *getPythonString(JNIEnv *env, jstring string) {
80 jsize len = (*env)->GetStringLength(env, string);
81 const jchar *chars = (*env)->GetStringChars(env, string, NULL);
83 PyObject *value = PyUnicode_DecodeUTF16((char*)chars, 2*len, NULL, NULL);
85 (*env)->ReleaseStringChars(env, string, chars);
89 PyObject *getPythonStringList(JNIEnv *env, jobjectArray value) {
90 jsize nitems = (*env)->GetArrayLength(env, value);
91 jint *values = (*env)->GetIntArrayElements(env, value, NULL);
92 jclass stringClass = (*env)->FindClass(env, STRING_CLASS);
95 PyObject *result = PyList_New(nitems);
96 for (i = 0; i < nitems; i++) {
97 jobject item = (*env)->GetObjectArrayElement(env, value, i);
98 if (item != NULL && (*env)->IsInstanceOf(env, item, stringClass)) {
99 PyList_SetItem(result, i, getPythonString(env, (jstring)item));
102 PyList_SetItem(result, i, Py_None);
106 (*env)->ReleaseIntArrayElements(env, value, values, JNI_ABORT);
110 PyObject *getPythonBooleanList(JNIEnv *env, jbooleanArray value) {
111 jsize nitems = (*env)->GetArrayLength(env, value);
112 jboolean *values = (*env)->GetBooleanArrayElements(env, value, NULL);
115 PyObject *result = PyList_New(nitems);
116 for (i = 0; i < nitems; i++) {
117 PyList_SetItem(result, i, getPythonBool(values[i]));
120 (*env)->ReleaseBooleanArrayElements(env, value, values, JNI_ABORT);
124 PyObject *getPythonByteArray(JNIEnv *env, jbyteArray value) {
125 jint len = (*env)->GetArrayLength(env, value);
126 jbyte *values = (*env)->GetByteArrayElements(env, value, NULL);
128 PyObject *result = PyByteArray_FromStringAndSize(values, len);
130 (*env)->ReleaseByteArrayElements(env, value, values, JNI_ABORT);
134 PyObject *getPythonIntegerList(JNIEnv *env, jintArray value) {
135 jsize nitems = (*env)->GetArrayLength(env, value);
136 jint *values = (*env)->GetIntArrayElements(env, value, NULL);
139 PyObject *result = PyList_New(nitems);
140 for (i = 0; i < nitems; i++) {
141 PyList_SetItem(result, i, PyLong_FromLong(values[i]));
144 (*env)->ReleaseIntArrayElements(env, value, values, JNI_ABORT);
148 PyObject *getPythonLongList(JNIEnv *env, jlongArray value) {
149 jsize nitems = (*env)->GetArrayLength(env, value);
150 jlong *values = (*env)->GetLongArrayElements(env, value, NULL);
153 PyObject *result = PyList_New(nitems);
154 for (i = 0; i < nitems; i++) {
155 PyList_SetItem(result, i, PyLong_FromLongLong(values[i]));
158 (*env)->ReleaseLongArrayElements(env, value, values, JNI_ABORT);
162 PyObject *getPythonFloatList(JNIEnv *env, jfloatArray value) {
163 jsize nitems = (*env)->GetArrayLength(env, value);
164 float *values = (*env)->GetFloatArrayElements(env, value, NULL);
167 PyObject *result = PyList_New(nitems);
168 for (i = 0; i < nitems; i++) {
169 PyList_SetItem(result, i, PyFloat_FromDouble((double)values[i]));
172 (*env)->ReleaseFloatArrayElements(env, value, values, JNI_ABORT);
176 PyObject *getPythonDoubleList(JNIEnv *env, jdoubleArray value) {
177 jsize nitems = (*env)->GetArrayLength(env, value);
178 double *values = (*env)->GetDoubleArrayElements(env, value, NULL);
181 PyObject *result = PyList_New(nitems);
182 for (i = 0; i < nitems; i++) {
183 PyList_SetItem(result, i, PyFloat_FromDouble(values[i]));
186 (*env)->ReleaseDoubleArrayElements(env, value, values, JNI_ABORT);
190 PyObject *getPythonNDArray(JNIEnv *env, jobject value) {
191 jclass ndarrayClass = (*env)->FindClass(env, NDARRAY_CLASS);
192 jmethodID dimsMethod = (*env)->GetMethodID(env, ndarrayClass, "dims", "()[I");
193 jmethodID getValuesMethod = (*env)->GetMethodID(env, ndarrayClass, "getValues", "()[D");
195 jintArray jdims = (*env)->CallObjectMethod(env, value, dimsMethod);
196 jsize ndims = (*env)->GetArrayLength(env, jdims);
197 jint *dims = (*env)->GetIntArrayElements(env, jdims, NULL);
199 jdoubleArray jvalues = (*env)->CallObjectMethod(env, value, getValuesMethod);
200 jsize len = (*env)->GetArrayLength(env, jvalues);
201 jdouble *values = (*env)->GetDoubleArrayElements(env, jvalues, NULL);
203 npy_intp *pyDims = (npy_intp*)malloc(ndims * sizeof(npy_intp));
205 jint i, nelem = ndims > 0 ? 1 : 0;
206 for (i = 0; i < ndims; i++) {
211 len = min(len, nelem);
214 PyObject *array = PyArray_EMPTY(ndims, pyDims, NPY_DOUBLE, 0);
215 double *data = (double *)PyArray_DATA((PyArrayObject*)array);
217 memcpy(data, values, len * sizeof(double));
221 (*env)->ReleaseDoubleArrayElements(env, jvalues, values, JNI_ABORT);
222 (*env)->ReleaseIntArrayElements(env, jdims, dims, JNI_ABORT);
228 PyObject *getPythonBooleanObject(JNIEnv *env, jobject object, jobject binding) {
229 jclass bindingClass = (*env)->FindClass(env, BOOLEANBINDING_CLASS);
230 jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)Z");
232 jboolean bvalue = (*env)->CallBooleanMethod(env, binding, getValueMethod, object);
233 return getPythonBool(bvalue);
236 PyObject *getPythonByteObject(JNIEnv *env, jobject object, jobject binding) {
237 jclass bindingClass = (*env)->FindClass(env, BYTEBINDING_CLASS);
238 jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)B");
240 jbyte v = (*env)->CallByteMethod(env, binding, getValueMethod, object);
241 return PyLong_FromLong(v);
244 PyObject *getPythonIntegerObject(JNIEnv *env, jobject object, jobject binding) {
245 jclass bindingClass = (*env)->FindClass(env, INTEGERBINDING_CLASS);
246 jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)I");
248 jint v = (*env)->CallIntMethod(env, binding, getValueMethod, object);
249 return PyLong_FromLong(v);
252 PyObject *getPythonLongObject(JNIEnv *env, jobject object, jobject binding) {
253 jclass bindingClass = (*env)->FindClass(env, LONGBINDING_CLASS);
254 jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)J");
256 jlong v = (*env)->CallLongMethod(env, binding, getValueMethod, object);
257 return PyLong_FromLongLong(v);
260 PyObject *getPythonFloatObject(JNIEnv *env, jobject object, jobject binding) {
261 jclass bindingClass = (*env)->FindClass(env, FLOATBINDING_CLASS);
262 jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)F");
264 jfloat v = (*env)->CallFloatMethod(env, binding, getValueMethod, object);
265 return PyFloat_FromDouble(v);
268 PyObject *getPythonDoubleObject(JNIEnv *env, jobject object, jobject binding) {
269 jclass bindingClass = (*env)->FindClass(env, DOUBLEBINDING_CLASS);
270 jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue_", "(L" OBJECT_CLASS ";)D");
272 jdouble v = (*env)->CallDoubleMethod(env, binding, getValueMethod, object);
273 return PyFloat_FromDouble(v);
276 PyObject *getPythonStringObject(JNIEnv *env, jobject object, jobject binding) {
277 jclass bindingClass = (*env)->FindClass(env, STRINGBINDING_CLASS);
278 jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue", "(L" OBJECT_CLASS ";)L" STRING_CLASS ";");
280 jobject string = (*env)->CallObjectMethod(env, binding, getValueMethod, object);
281 jsize len = (*env)->GetStringLength(env, string);
282 const jchar *chars = (*env)->GetStringChars(env, string, NULL);
284 PyObject *value = PyUnicode_DecodeUTF16((char*)chars, 2*len, NULL, NULL);
286 (*env)->ReleaseStringChars(env, string, chars);
290 PyObject *getPythonRecordObject(JNIEnv *env, jobject object, jobject binding) {
291 jclass bindingClass = (*env)->FindClass(env, RECORDBINDING_CLASS);
292 jmethodID typeMethod = (*env)->GetMethodID(env, bindingClass, "type", "()L" RECORDTYPE_CLASS ";");
293 jmethodID getComponent = (*env)->GetMethodID(env, bindingClass, "getComponent", "(L" OBJECT_CLASS ";I)L" OBJECT_CLASS ";");
294 jmethodID getComponentBinding = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "(I)L" BINDING_CLASS ";");
296 jclass recordType = (*env)->FindClass(env, RECORDTYPE_CLASS);
297 jmethodID getTypeComponent = (*env)->GetMethodID(env, recordType, "getComponent", "(I)L" COMPONENT_CLASS ";");
298 jmethodID getComponentCount = (*env)->GetMethodID(env, recordType, "getComponentCount", "()I");
300 jclass componentClass = (*env)->FindClass(env, COMPONENT_CLASS);
301 jfieldID nameField = (*env)->GetFieldID(env, componentClass, "name", "L" STRING_CLASS ";");
303 jobject type = (*env)->CallObjectMethod(env, binding, typeMethod);
304 jint n = (*env)->CallIntMethod(env, type, getComponentCount);
307 PyObject *result = PyDict_New();
308 for (i = 0; i < n; i++) {
309 jobject recordTypeComponent = (*env)->CallObjectMethod(env, type, getComponent, i);
310 jstring fieldName = (jstring)(*env)->GetObjectField(env, recordTypeComponent, nameField);
311 jobject componentObject = (*env)->CallObjectMethod(env, binding, getComponent, object, i);
312 jobject componentBinding = (*env)->CallObjectMethod(env, binding, getComponentBinding, i);
314 PyObject *item = getPythonObject(env, componentObject, componentBinding);
315 PyDict_SetItem(result, getPythonString(env, fieldName), item);
321 PyObject *getPythonArrayObject(JNIEnv *env, jobject object, jobject binding) {
322 jclass bindingClass = (*env)->FindClass(env, ARRAYBINDING_CLASS);
323 jmethodID componentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "()L" BINDING_CLASS ";");
324 jmethodID sizeMethod = (*env)->GetMethodID(env, bindingClass, "size", "(L" OBJECT_CLASS ";)I");
325 jmethodID getMethod = (*env)->GetMethodID(env, bindingClass, "get", "(L" OBJECT_CLASS ";I)L" OBJECT_CLASS ";");
327 jobject componentBinding = (*env)->CallObjectMethod(env, binding, componentBindingMethod);
329 jint size = (*env)->CallIntMethod(env, binding, sizeMethod, object);
331 PyObject *result = PyList_New(size);
334 for (i = 0; i < size; i++) {
335 jobject item = (*env)->CallObjectMethod(env, binding, getMethod, object, i);
337 PyList_SetItem(result, i, getPythonObject(env, item, componentBinding));
339 PyList_SetItem(result, i, Py_None);
345 PyObject *getPythonMapObject(JNIEnv *env, jobject object, jobject binding) {
346 jclass objectClass = (*env)->FindClass(env, OBJECT_CLASS);
347 jclass bindingClass = (*env)->FindClass(env, MAPBINDING_CLASS);
348 jmethodID getKeyBindingMethod = (*env)->GetMethodID(env, bindingClass, "getKeyBinding", "()L" BINDING_CLASS ";");
349 jmethodID getValueBindingMethod = (*env)->GetMethodID(env, bindingClass, "getValueBinding", "()L" BINDING_CLASS ";");
350 jmethodID sizeMethod = (*env)->GetMethodID(env, bindingClass, "size", "(L" OBJECT_CLASS ";)I");
351 jmethodID getAllMethod = (*env)->GetMethodID(env, bindingClass, "getAll", "(L" OBJECT_CLASS ";[L" OBJECT_CLASS ";[L" OBJECT_CLASS ";)V");
353 jobject keyBinding = (*env)->CallObjectMethod(env, binding, getKeyBindingMethod);
354 jobject valueBinding = (*env)->CallObjectMethod(env, binding, getValueBindingMethod);
356 jint size = (*env)->CallIntMethod(env, binding, sizeMethod, object);
357 jobjectArray keys = (*env)->NewObjectArray(env, size, objectClass, NULL);
358 jobjectArray values = (*env)->NewObjectArray(env, size, objectClass, NULL);
360 PyObject *result = PyDict_New();
363 (*env)->CallVoidMethod(env, binding, getAllMethod, object, keys, values);
365 for (i = 0; i < size; i++) {
366 jobject key = (*env)->GetObjectArrayElement(env, keys, i);
367 jobject item = (*env)->GetObjectArrayElement(env, values, i);
368 PyDict_SetItem(result, getPythonObject(env, key, keyBinding), getPythonObject(env, item, valueBinding));
371 (*env)->DeleteLocalRef(env, keys);
372 (*env)->DeleteLocalRef(env, values);
377 PyObject *getPythonOptionalObject(JNIEnv *env, jobject object, jobject binding) {
378 jclass bindingClass = (*env)->FindClass(env, OPTIONALBINDING_CLASS);
379 jmethodID hasValueMethod = (*env)->GetMethodID(env, bindingClass, "hasValue", "(L" OBJECT_CLASS ";)Z");
381 jboolean hasValue = (*env)->CallBooleanMethod(env, binding, hasValueMethod, object);
384 jmethodID componentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "()L" BINDING_CLASS ";");
385 jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "hasValue", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");
387 jobject componentBinding = (*env)->CallObjectMethod(env, binding, componentBindingMethod);
388 jobject value = (*env)->CallObjectMethod(env, binding, getValueMethod, object);
390 return getPythonObject(env, value, componentBinding);
397 PyObject *getPythonUnionObject(JNIEnv *env, jobject object, jobject binding) {
398 jclass bindingClass = (*env)->FindClass(env, UNIONBINDING_CLASS);
399 jmethodID typeMethod = (*env)->GetMethodID(env, bindingClass, "type", "()L" RECORDTYPE_CLASS ";");
400 jmethodID getTagMethod = (*env)->GetMethodID(env, bindingClass, "getTag", "(L" OBJECT_CLASS ";)I");
401 jmethodID getValueMethod = (*env)->GetMethodID(env, bindingClass, "getValue", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");
402 jmethodID getComponentBinding = (*env)->GetMethodID(env, bindingClass, "getComponentBinding", "(I)L" BINDING_CLASS ";");
404 jclass unionType = (*env)->FindClass(env, UNIONTYPE_CLASS);
405 jmethodID getTypeComponent = (*env)->GetMethodID(env, unionType, "getComponent", "(I)L" COMPONENT_CLASS ";");
407 jclass componentClass = (*env)->FindClass(env, COMPONENT_CLASS);
408 jfieldID nameField = (*env)->GetFieldID(env, componentClass, "name", "L" STRING_CLASS ";");
410 jint tag = (*env)->CallIntMethod(env, binding, getTagMethod, object);
411 jobject value = (*env)->CallObjectMethod(env, binding, getValueMethod, object);
413 jobject type = (*env)->CallObjectMethod(env, binding, typeMethod);
414 jobject typeComponent = (*env)->CallObjectMethod(env, type, getTypeComponent, tag);
415 jstring compName = (*env)->GetObjectField(env, typeComponent, nameField);
417 jobject componentBinding = (*env)->CallObjectMethod(env, binding, getComponentBinding, tag);
419 PyObject *result = PyTuple_New(2);
420 PyTuple_SetItem(result, 0, getPythonString(env, compName));
421 PyTuple_SetItem(result, 1, getPythonObject(env, value, componentBinding));
426 PyObject *getPythonVariantObject(JNIEnv *env, jobject object, jobject binding) {
427 jclass bindingClass = (*env)->FindClass(env, VARIANTBINDING_CLASS);
428 jmethodID getContentMethod = (*env)->GetMethodID(env, bindingClass, "getContent", "(L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");
429 jmethodID getContentBindingMethod = (*env)->GetMethodID(env, bindingClass, "getContentBinding", "(L" OBJECT_CLASS ";)L" BINDING_CLASS ";");
431 jobject content = (*env)->CallObjectMethod(env, binding, getContentMethod, object);
432 jobject contentBinding = (*env)->CallObjectMethod(env, binding, getContentBindingMethod, object);
434 return getPythonObject(env, content, contentBinding);
437 PyObject *getPythonObject(JNIEnv *env, jobject value, jobject binding) {
438 jclass booleanBinding = (*env)->FindClass(env, BOOLEANBINDING_CLASS);
439 jclass byteBinding = (*env)->FindClass(env, BYTEBINDING_CLASS);
440 jclass integerBinding = (*env)->FindClass(env, INTEGERBINDING_CLASS);
441 jclass longBinding = (*env)->FindClass(env, LONGBINDING_CLASS);
442 jclass floatBinding = (*env)->FindClass(env, FLOATBINDING_CLASS);
443 jclass doubleBinding = (*env)->FindClass(env, DOUBLEBINDING_CLASS);
444 jclass stringBinding = (*env)->FindClass(env, STRINGBINDING_CLASS);
445 jclass recordBinding = (*env)->FindClass(env, RECORDBINDING_CLASS);
446 jclass arrayBinding = (*env)->FindClass(env, ARRAYBINDING_CLASS);
447 jclass mapBinding = (*env)->FindClass(env, MAPBINDING_CLASS);
448 jclass optionalBinding = (*env)->FindClass(env, OPTIONALBINDING_CLASS);
449 jclass untionBinding = (*env)->FindClass(env, UNIONBINDING_CLASS);
450 jclass variantBinding = (*env)->FindClass(env, VARIANTBINDING_CLASS);
455 if ((*env)->IsInstanceOf(env, binding, booleanBinding)) {
456 return getPythonBooleanObject(env, value, binding);
458 else if ((*env)->IsInstanceOf(env, binding, byteBinding)) {
459 return getPythonByteObject(env, value, binding);
461 else if ((*env)->IsInstanceOf(env, binding, integerBinding)) {
462 return getPythonIntegerObject(env, value, binding);
464 else if ((*env)->IsInstanceOf(env, binding, longBinding)) {
465 return getPythonLongObject(env, value, binding);
467 else if ((*env)->IsInstanceOf(env, binding, floatBinding)) {
468 return getPythonFloatObject(env, value, binding);
470 else if ((*env)->IsInstanceOf(env, binding, doubleBinding)) {
471 return getPythonDoubleObject(env, value, binding);
473 else if ((*env)->IsInstanceOf(env, binding, stringBinding)) {
474 return getPythonStringObject(env, value, binding);
476 else if ((*env)->IsInstanceOf(env, binding, recordBinding)) {
477 return getPythonRecordObject(env, value, binding);
479 else if ((*env)->IsInstanceOf(env, binding, arrayBinding)) {
480 return getPythonArrayObject(env, value, binding);
482 else if ((*env)->IsInstanceOf(env, binding, mapBinding)) {
483 return getPythonMapObject(env, value, binding);
485 else if ((*env)->IsInstanceOf(env, binding, optionalBinding)) {
486 return getPythonOptionalObject(env, value, binding);
488 else if ((*env)->IsInstanceOf(env, binding, untionBinding)) {
489 return getPythonUnionObject(env, value, binding);
491 else if ((*env)->IsInstanceOf(env, binding, variantBinding)) {
492 return getPythonVariantObject(env, value, binding);
499 void setPythonVariable(PyObject *module, PyObject *name, PyObject *value) {
501 PyDict_SetItem(PyModule_GetDict(module), name, value);
508 static npy_intp nContiguous(int d, int nd, npy_intp *strides, npy_intp *dims, npy_intp *ncont) {
514 npy_intp n = nContiguous(d+1, nd, strides, dims, ncont);
515 ncont[d] = n > 0 && strides[d] == sizeof(double) * n ? dims[d] * n : 0;
520 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) {
522 (*env)->SetDoubleArrayRegion(env, array, (jint)*offset, (jint)ncont[d], data);
527 for (i = 0; i < dims[d]; i++) {
528 copyDoubleArrayValues(env, array, (double*)((char*)data + strides[d] * i), offset, d+1, nd, strides, dims, ncont);
533 jobject pythonBoolAsBooleanObject(JNIEnv *env, PyObject *value) {
534 jclass booleanClass = (*env)->FindClass(env, "java/lang/Boolean");
535 jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, booleanClass, "valueOf", "(Z)Ljava/lang/Boolean;");
537 return (*env)->CallStaticObjectMethod(env, booleanClass, valueOfMethod, (jboolean)(value == Py_True));
540 jobject pythonLongAsLongObject(JNIEnv *env, PyObject *value) {
541 jclass longClass = (*env)->FindClass(env, "java/lang/Long");
542 jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, longClass, "valueOf", "(J)Ljava/lang/Long;");
544 return (*env)->CallStaticObjectMethod(env, longClass, valueOfMethod, PyLong_AsLongLong(value));
547 jobject pythonFloatAsDoubleObject(JNIEnv *env, PyObject *value) {
548 jclass doubleClass = (*env)->FindClass(env, "java/lang/Double");
549 jmethodID valueOfMethod = (*env)->GetStaticMethodID(env, doubleClass, "valueOf", "(D)Ljava/lang/Double;");
551 return (*env)->CallStaticObjectMethod(env, doubleClass, valueOfMethod, PyFloat_AsDouble(value));
554 jobject pythonByteArrayAsByteArray(JNIEnv *env, PyObject *value) {
555 Py_ssize_t size = PyByteArray_Size(value);
556 jbyteArray result = (*env)->NewByteArray(env, (jsize)size);
557 char *bytes = PyByteArray_AsString(value);
559 (*env)->SetByteArrayRegion(env, result, 0, size, bytes);
564 jstring pythonStringAsJavaString(JNIEnv *env, PyObject *string) {
565 PyObject *utf16Value = PyUnicode_AsUTF16String(string);
566 Py_ssize_t len = PyBytes_Size(utf16Value) / 2;
567 char *bytes = PyBytes_AsString(utf16Value);
569 // Create Java string, skipping the byte order mark in the beginning
570 jstring result = (*env)->NewString(env, (jchar *)bytes + 1, (jsize)min(len, JAVA_MAXINT) - 1);
572 Py_XDECREF(utf16Value);
577 jobjectArray pythonSequenceAsStringArray(JNIEnv *env, PyObject *seq) {
578 Py_ssize_t len = PySequence_Size(seq);
579 jsize jlen = (jsize)min(len, JAVA_MAXINT);
580 jobjectArray array = (*env)->NewObjectArray(env, jlen, (*env)->FindClass(env, STRING_CLASS), NULL);
584 for (i = 0; i < jlen; i++) {
585 PyObject *item = PySequence_GetItem(seq, i);
586 if (PyUnicode_Check(item)) {
587 jstring value = pythonStringAsJavaString(env, item);
588 (*env)->SetObjectArrayElement(env, array, i, value);
591 throwPythonException(env, "List item not a string");
599 jdoubleArray pythonSequenceAsDoubleArray(JNIEnv *env, PyObject *seq) {
600 Py_ssize_t len = PySequence_Size(seq);
601 jsize jlen = (jsize)min(len, JAVA_MAXINT);
602 jdoubleArray array = (*env)->NewDoubleArray(env, jlen);
606 for (i = 0; i < jlen; i++) {
607 PyObject *item = PySequence_GetItem(seq, i);
608 if (PyFloat_Check(item)) {
609 double value = PyFloat_AsDouble(item);
610 (*env)->SetDoubleArrayRegion(env, array, i, 1, &value);
613 throwPythonException(env, "List item not a floating point value");
621 jobject pythonObjectAsObject(JNIEnv *env, PyObject *value) {
622 if (PyBool_Check(value))
623 return pythonBoolAsBooleanObject(env, value);
624 else if (PyLong_Check(value))
625 return pythonLongAsLongObject(env, value);
626 else if (PyFloat_Check(value))
627 return pythonFloatAsDoubleObject(env, value);
628 else if (PyUnicode_Check(value))
629 return pythonStringAsJavaString(env, value);
630 else if (PyByteArray_Check(value))
631 return pythonByteArrayAsByteArray(env, value);
632 else if (PyDict_Check(value))
633 return pythonDictionaryAsMap(env, value);
634 else if (hasNumpy && PyArray_Check(value))
635 return pythonArrayAsNDArray(env, (PyArrayObject *)value);
636 else if (PySequence_Check(value))
637 return pythonSequenceAsObjectArray(env, value);
642 jobjectArray pythonSequenceAsObjectArray(JNIEnv *env, PyObject *seq) {
643 Py_ssize_t len = PySequence_Size(seq);
644 jsize jlen = (jsize)min(len, JAVA_MAXINT);
645 jobjectArray array = (*env)->NewObjectArray(env, jlen, (*env)->FindClass(env, OBJECT_CLASS), NULL);
649 for (i = 0; i < jlen; i++) {
650 PyObject *item = PySequence_GetItem(seq, i);
651 jobject object = pythonObjectAsObject(env, item);
652 (*env)->SetObjectArrayElement(env, array, i, object);
658 jbooleanArray pythonSequenceAsBooleanArray(JNIEnv *env, PyObject *seq) {
659 Py_ssize_t len = PySequence_Size(seq);
660 jsize jlen = (jsize)min(len, JAVA_MAXINT);
661 jbooleanArray array = (*env)->NewBooleanArray(env, jlen);
665 for (i = 0; i < jlen; i++) {
666 PyObject *item = PySequence_GetItem(seq, i);
667 if (PyBool_Check(item)) {
668 jboolean value = item == Py_True;
669 (*env)->SetBooleanArrayRegion(env, array, i, 1, &value);
672 throwPythonException(env, "List item not a boolean");
680 jintArray pythonSequenceAsIntegerArray(JNIEnv *env, PyObject *seq) {
681 Py_ssize_t len = PySequence_Size(seq);
682 jsize jlen = (jsize)min(len, JAVA_MAXINT);
683 jintArray array = (*env)->NewIntArray(env, jlen);
687 for (i = 0; i < jlen; i++) {
688 PyObject *item = PySequence_GetItem(seq, i);
689 if (PyLong_Check(item)) {
690 jint value = PyLong_AsLong(item);
691 (*env)->SetIntArrayRegion(env, array, i, 1, &value);
694 throwPythonException(env, "List item not an integer");
702 jlongArray pythonSequenceAsLongArray(JNIEnv *env, PyObject *seq) {
703 Py_ssize_t len = PySequence_Size(seq);
704 jsize jlen = (jsize)min(len, JAVA_MAXINT);
705 jlongArray array = (*env)->NewLongArray(env, jlen);
709 for (i = 0; i < jlen; i++) {
710 PyObject *item = PySequence_GetItem(seq, i);
711 if (PyLong_Check(item)) {
712 jlong value = PyLong_AsLongLong(item);
713 (*env)->SetLongArrayRegion(env, array, i, 1, &value);
716 throwPythonException(env, "List item not an integer");
724 jobject pythonArrayAsNDArray(JNIEnv *env, PyArrayObject *array) {
725 jclass ndarrayClass = (*env)->FindClass(env, NDARRAY_CLASS);
726 jmethodID constructor = (*env)->GetMethodID(env, ndarrayClass, "<init>", "([I[D)V");
728 int ndims = PyArray_NDIM(array);
729 npy_intp *dims = PyArray_DIMS(array);
731 npy_intp len = PyArray_Size((PyObject*)array);
732 double *values = (double*)PyArray_DATA(array);
734 jboolean isFortran = PyArray_ISFORTRAN(array) != 0;
738 if (len > JAVA_MAXINT) {
739 throwPythonException(env, "Array too large");
744 jintArray jdims = (*env)->NewIntArray(env, ndims);
745 jdoubleArray jvalues = (*env)->NewDoubleArray(env, (jsize)len);
747 for (i = 0; i < ndims; i++) {
748 jint dim = (jint)dims[i];
749 (*env)->SetIntArrayRegion(env, jdims, i, 1, &dim);
752 if (PyArray_IS_C_CONTIGUOUS(array)) {
753 (*env)->SetDoubleArrayRegion(env, jvalues, 0, (jsize)len, values);
757 npy_intp *strides = PyArray_STRIDES(array);
758 npy_intp *ncont = (npy_intp*)malloc((ndims + 1) * sizeof(npy_intp));
759 nContiguous(0, ndims, strides, dims, ncont);
760 copyDoubleArrayValues(env, jvalues, values, &offset, 0, ndims, strides, dims, ncont);
764 return (*env)->NewObject(env, ndarrayClass, constructor, jdims, jvalues, isFortran);
768 jobject pythonDictionaryAsMap(JNIEnv *env, PyObject *dict) {
769 jclass hashmapClass = (*env)->FindClass(env, "java/util/HashMap");
770 jmethodID constructor = (*env)->GetMethodID(env, hashmapClass, "<init>", "(I)V");
771 jmethodID putMethod = (*env)->GetMethodID(env, hashmapClass, "put", "(L" OBJECT_CLASS ";L" OBJECT_CLASS ";)L" OBJECT_CLASS ";");
773 Py_ssize_t size = PyDict_Size(dict);
774 jobject map = (*env)->NewObject(env, hashmapClass, constructor, (jint)size);
776 PyObject *key, *value;
779 while (PyDict_Next(dict, &pos, &key, &value)) {
780 jobject keyObject = pythonObjectAsObject(env, key);
781 jobject valueObject = pythonObjectAsObject(env, value);
782 (*env)->CallObjectMethod(env, map, putMethod, keyObject, valueObject);
788 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBooleanVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jboolean value) {
789 PyObject *module = (PyObject*)contextID;
791 PyObject *pythonName = getPythonString(env, variableName);
792 PyObject *val = getPythonBool(value);
794 setPythonVariable(module, pythonName, val);
797 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonBooleanArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jbooleanArray value) {
798 PyObject *module = (PyObject*)contextID;
800 PyObject *pythonName = getPythonString(env, variableName);
801 PyObject *val = getPythonBooleanList(env, value);
803 setPythonVariable(module, pythonName, val);
806 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonLongVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jlong value) {
807 PyObject *module = (PyObject*)contextID;
809 PyObject *pythonName = getPythonString(env, variableName);
810 PyObject *val = PyLong_FromLongLong(value);
812 setPythonVariable(module, pythonName, val);
815 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jintArray value) {
816 PyObject *module = (PyObject*)contextID;
818 PyObject *pythonName = getPythonString(env, variableName);
819 PyObject *val = getPythonIntegerList(env, value);
821 setPythonVariable(module, pythonName, val);
824 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonLongArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jlongArray value) {
825 PyObject *module = (PyObject*)contextID;
827 PyObject *pythonName = getPythonString(env, variableName);
828 PyObject *val = getPythonLongList(env, value);
830 setPythonVariable(module, pythonName, val);
833 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdouble value) {
834 PyObject *module = (PyObject*)contextID;
836 PyObject *pythonName = getPythonString(env, variableName);
837 PyObject *val = PyFloat_FromDouble(value);
839 setPythonVariable(module, pythonName, val);
842 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonFloatArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jfloatArray value) {
843 PyObject *module = (PyObject*)contextID;
845 PyObject *pythonName = getPythonString(env, variableName);
846 PyObject *val = getPythonFloatList(env, value);
848 setPythonVariable(module, pythonName, val);
851 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jdoubleArray value) {
852 PyObject *module = (PyObject*)contextID;
854 PyObject *pythonName = getPythonString(env, variableName);
855 PyObject *val = getPythonDoubleList(env, value);
857 setPythonVariable(module, pythonName, val);
860 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jstring value) {
861 PyObject *module = (PyObject*)contextID;
863 PyObject *pythonName = getPythonString(env, variableName);
864 PyObject *val = getPythonString(env, value);
866 setPythonVariable(module, pythonName, val);
869 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobjectArray value) {
870 PyObject *module = (PyObject*)contextID;
872 PyObject *pythonName = getPythonString(env, variableName);
873 PyObject *val = getPythonStringList(env, value);
875 setPythonVariable(module, pythonName, val);
878 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value) {
879 PyObject *module = (PyObject*)contextID;
882 throwPythonException(env, "Importing numpy failed");
887 PyObject *pythonName = getPythonString(env, variableName);
888 PyObject *val = getPythonNDArray(env, value);
890 setPythonVariable(module, pythonName, val);
894 JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonVariantVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName, jobject value, jobject binding) {
895 PyObject *module = (PyObject*)contextID;
897 PyObject *pythonName = getPythonString(env, variableName);
898 PyObject *val = getPythonObject(env, value, binding);
900 setPythonVariable(module, pythonName, val);
903 JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePythonStatementImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring statement) {
904 PyObject *module = (PyObject*)contextID;
906 const char *utfchars = (*env)->GetStringUTFChars(env, statement, NULL);
908 PyEval_RestoreThread(main_ts);
913 globals = PyModule_GetDict(module);
916 PyObject *result = PyRun_String(utfchars, Py_file_input, globals, globals);
918 PyObject *exceptionType = PyErr_Occurred();
919 if (exceptionType != NULL) {
920 PyObject *exception, *traceback;
921 PyErr_Fetch(&exceptionType, &exception, &traceback);
924 PyObject *tracebackModule = PyImport_ImportModule("traceback");
925 if (tracebackModule != NULL) {
926 PyObject *formatExc = PyDict_GetItemString(PyModule_GetDict(tracebackModule), "format_exception");
927 if (formatExc != NULL) {
928 PyObject *args = PyTuple_Pack(3, exceptionType, exception, traceback);
929 PyObject *message = PyObject_CallObject(formatExc, args);
930 if (message != NULL) {
931 PyObject *emptyStr = PyUnicode_FromString("");
932 PyObject *joined = PyUnicode_Join(emptyStr, message);
933 char *messageStr = PyUnicode_AsUTF8(joined);
934 throwPythonException(env, messageStr);
940 throwPythonException(env, "Internal error, no message");
943 Py_DECREF(formatExc);
946 throwPythonException(env, "Internal error, no format_exc function");
948 Py_DECREF(tracebackModule);
951 throwPythonException(env, "Internal error, no traceback module");
957 (*env)->ReleaseStringUTFChars(env, statement, utfchars);
959 return result != NULL ? 0 : 1;
964 JNIEXPORT jstring JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
965 PyObject *module = (PyObject*)contextID;
967 PyObject *pythonName = getPythonString(env, variableName);
969 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
971 throwPythonException(env, "Python variable not found");
975 if (!PyUnicode_Check(value)) {
976 throwPythonException(env, "Python variable not a string");
981 jstring result = pythonStringAsJavaString(env, value);
986 JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonStringArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
987 PyObject *module = (PyObject*)contextID;
989 PyObject *pythonName = getPythonString(env, variableName);
991 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
993 throwPythonException(env, "Python variable not found");
997 if (!PySequence_Check(value)) {
998 throwPythonException(env, "Python variable not a sequence");
1003 jobjectArray result = pythonSequenceAsStringArray(env, value);
1008 JNIEXPORT jboolean JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonBooleanVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
1009 PyObject *module = (PyObject*)contextID;
1011 PyObject *pythonName = getPythonString(env, variableName);
1013 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
1014 if (value == NULL) {
1015 throwPythonException(env, "Python variable not found");
1019 if (!PyBool_Check(value)) {
1020 throwPythonException(env, "Python variable not a boolean");
1024 return value == Py_True;
1027 JNIEXPORT jbooleanArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonBooleanArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
1028 PyObject *module = (PyObject*)contextID;
1030 PyObject *pythonName = getPythonString(env, variableName);
1032 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
1033 if (value == NULL) {
1034 throwPythonException(env, "Python variable not found");
1038 if (!PySequence_Check(value)) {
1039 throwPythonException(env, "Python variable not a sequence");
1044 jbooleanArray result = pythonSequenceAsBooleanArray(env, value);
1049 JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLongVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
1050 PyObject *module = (PyObject*)contextID;
1052 PyObject *pythonName = getPythonString(env, variableName);
1054 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
1055 if (value == NULL) {
1056 throwPythonException(env, "Python variable not found");
1060 if (!PyLong_Check(value)) {
1061 throwPythonException(env, "Python variable not an integer");
1066 jlong result = PyLong_AsLongLong(value);
1071 JNIEXPORT jintArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonIntegerArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
1072 PyObject *module = (PyObject*)contextID;
1074 PyObject *pythonName = getPythonString(env, variableName);
1076 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
1077 if (value == NULL) {
1078 throwPythonException(env, "Python variable not found");
1082 if (!PySequence_Check(value)) {
1083 throwPythonException(env, "Python variable not a sequence");
1088 jintArray result = pythonSequenceAsIntegerArray(env, value);
1093 JNIEXPORT jlongArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLongArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
1094 PyObject *module = (PyObject*)contextID;
1096 PyObject *pythonName = getPythonString(env, variableName);
1098 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
1099 if (value == NULL) {
1100 throwPythonException(env, "Python variable not found");
1104 if (!PySequence_Check(value)) {
1105 throwPythonException(env, "Python variable not a sequence");
1110 jlongArray result = pythonSequenceAsLongArray(env, value);
1115 JNIEXPORT jdouble JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
1116 PyObject *module = (PyObject*)contextID;
1118 PyObject *pythonName = getPythonString(env, variableName);
1120 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
1121 if (value == NULL) {
1122 throwPythonException(env, "Python variable not found");
1126 if (!PyFloat_Check(value)) {
1127 throwPythonException(env, "Python variable not a float");
1132 jdouble result = PyFloat_AsDouble(value);
1137 JNIEXPORT jdoubleArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonDoubleArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
1138 PyObject *module = (PyObject*)contextID;
1140 PyObject *pythonName = getPythonString(env, variableName);
1142 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
1143 if (value == NULL) {
1144 throwPythonException(env, "Python variable not found");
1148 if (!PySequence_Check(value)) {
1149 throwPythonException(env, "Python variable not a sequence");
1154 jdoubleArray result = pythonSequenceAsDoubleArray(env, value);
1159 JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonNDArrayVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
1160 PyObject *module = (PyObject*)contextID;
1163 throwPythonException(env, "Importing numpy failed");
1168 PyObject *pythonName = getPythonString(env, variableName);
1170 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
1171 if (value == NULL) {
1172 throwPythonException(env, "Python variable not found");
1176 if (!PyArray_Check(value)) {
1177 throwPythonException(env, "Python variable not an ndarray");
1181 if (PyArray_TYPE((PyArrayObject*)value) != NPY_DOUBLE) {
1182 throwPythonException(env, "Only ndarrays of type double are supported");
1187 jobject result = pythonArrayAsNDArray(env, (PyArrayObject *)value);
1193 JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariantVariableImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
1194 PyObject *module = (PyObject*)contextID;
1196 PyObject *pythonName = getPythonString(env, variableName);
1198 PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);
1199 if (value == NULL) {
1200 throwPythonException(env, "Python variable not found");
1204 hasNumpy = _import_array() != -1;
1207 jobject result = pythonObjectAsObject(env, value);
1212 JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariableTypeImpl(JNIEnv *env, jobject thisObj, jlong contextID, jstring variableName) {
1213 PyObject *module = (PyObject*)contextID;
1214 PyObject *dict = PyModule_GetDict(module);
1216 PyObject *pythonName = getPythonString(env, variableName);
1218 if (!PyDict_Contains(dict, pythonName)) {
1223 PyObject *value = PyDict_GetItem(dict, pythonName);
1227 if (PyBool_Check(value))
1229 else if (PyLong_Check(value))
1231 else if (PyFloat_Check(value))
1233 else if (PyUnicode_Check(value))
1235 else if (PyByteArray_Check(value))
1237 else if (PyDict_Check(value))
1239 else if (hasNumpy && PyArray_Check(value))
1241 else if (PySequence_Check(value))
1250 JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonVariableNamesImpl(JNIEnv *env, jobject thisObj, jlong contextID) {
1251 PyObject *module = (PyObject*)contextID;
1252 PyObject *dict = PyModule_GetDict(module);
1254 PyObject *keys = PyDict_Keys(dict);
1255 Py_ssize_t size = PyList_Size(keys);
1257 jobjectArray result = (*env)->NewObjectArray(env, (jsize)size, (*env)->FindClass(env, STRING_CLASS), NULL);
1260 for (i = 0; i < size; i++) {
1261 jstring javaName = pythonStringAsJavaString(env, PyList_GetItem(keys, i));
1262 (*env)->SetObjectArrayElement(env, result, (jint)i, javaName);
1270 BOOL __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1271 //extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
1275 case DLL_PROCESS_ATTACH:
1276 // attach to process
1277 // return FALSE to fail DLL load
1280 case DLL_PROCESS_DETACH:
1281 // detach from process
1284 case DLL_THREAD_ATTACH:
1288 case DLL_THREAD_DETACH:
1289 // detach from thread
1292 return TRUE; // succesful