jboolean followCallGenericJavaCallback(CallTempStruct* call, ValueType returnType, DCValue* result, void* callback) { JNIEnv* env = call->env; jobject ret = dcCallPointer(call->vm, callback); if ((*env)->ExceptionCheck(env)) return JNI_FALSE; switch (returnType) { case eIntValue: result->i = UnboxInt(env, ret); break; case eLongValue: result->l = UnboxLong(env, ret); break; case eShortValue: result->s = UnboxShort(env, ret); break; case eByteValue: result->c = UnboxByte(env, ret); break; case eFloatValue: result->f = UnboxFloat(env, ret); break; case eDoubleValue: result->d = UnboxDouble(env, ret); break; case eBooleanValue: result->c = UnboxBoolean(env, ret); break; case eCLongValue: { jlong v; if ((*env)->IsInstanceOf(env, ret, gCLongClass)) v = UnboxCLong(env, ret); else v = UnboxLong(env, ret); if (sizeof(long) == 4) result->i = (int)v; else result->l = v; break; } case eSizeTValue: { jlong v; if ((*env)->IsInstanceOf(env, ret, gCLongClass)) v = UnboxSizeT(env, ret); else v = UnboxLong(env, ret); if (sizeof(size_t) == 4) result->i = (int)v; else result->L = v; break; } case eVoidValue: assert(ret == NULL); break; case eIntFlagSet: result->i = (jint)getFlagValue(env, ret); break; case ePointerValue: result->p = ret ? getPointerPeer(env, (void*)ret) : NULL; call->pCallIOs++; break; case eWCharValue: switch (sizeof(wchar_t)) { case 1: result->c = (char)UnboxChar(env, ret); break; case 2: result->s = (short)UnboxChar(env, ret); break; case 4: result->i = UnboxInt(env, ret); break; default: throwException(env, "Invalid wchar_t size !"); return JNI_FALSE; } break; default: throwException(env, "Invalid return value type !"); return JNI_FALSE; } return JNI_TRUE; }
jboolean followArgs(CallTempStruct* call, DCArgs* args, int nTypes, ValueType* pTypes, jboolean toJava, jboolean isVarArgs) { JNIEnv* env = call->env; int iParam; //printf("ARGS : %d args\n", (int)nTypes); for (iParam = 0; iParam < nTypes; iParam++) { ValueType type = pTypes[iParam]; switch (type) { case eIntFlagSet: { jobject callIO = call && call->pCallIOs ? *(call->pCallIOs++) : NULL; if (toJava) { int flags = dcbArgInt(args); jobject obj = createPointerFromIO(env, JLONG_TO_PTR ((jlong)flags), callIO); dcArgPointer(call->vm, obj); } else { int arg = (jint)getFlagValue(env, (jobject)dcbArgPointer(args)); if (isVarArgs) dcArgPointer(call->vm, (void*)(ptrdiff_t)arg); else dcArgInt(call->vm, arg); } } break; case eIntValue: { int arg = dcbArgInt(args); if (isVarArgs) dcArgPointer(call->vm, (void*)(ptrdiff_t)arg); else dcArgInt(call->vm, arg); } break; #define ARG_BOXED_INTEGRAL(type, capitalized) \ { \ if (toJava) { \ type arg = (sizeof(type) == 4) ? (type)dcbArgInt(args) : (type)dcbArgLongLong(args); \ dcArgPointer(call->vm, Box ## capitalized(env, arg)); \ } else { \ jobject parg = dcbArgPointer(args); \ jlong arg = Unbox ## capitalized(env, parg); \ if (isVarArgs) \ dcArgPointer(call->vm, (void*)(ptrdiff_t)arg); \ else if (sizeof(type) == 4) \ dcArgInt(call->vm, (jint)arg); \ else \ dcArgLongLong(call->vm, (jlong)arg); \ } \ } #define ARG_UNBOXED_INTEGRAL(type, capitalized) \ { \ if (toJava) { \ type arg = (sizeof(type) == 4) ? (type)dcbArgInt(args) : (type)dcbArgLongLong(args); \ dcArgLongLong(call->vm, (jlong)arg); \ } else { \ jlong arg = dcbArgLongLong(args); \ if (isVarArgs) \ dcArgPointer(call->vm, (void*)(ptrdiff_t)arg); \ else if (sizeof(type) == 4) \ dcArgInt(call->vm, (jint)arg); \ else \ dcArgLongLong(call->vm, (jlong)arg); \ } \ } case eCLongValue: ARG_UNBOXED_INTEGRAL(long, CLong); break; case eSizeTValue: ARG_UNBOXED_INTEGRAL(size_t, SizeT); break; case eCLongObjectValue: ARG_BOXED_INTEGRAL(long, CLong); break; case eSizeTObjectValue: ARG_BOXED_INTEGRAL(size_t, SizeT); break; case eTimeTObjectValue: ARG_BOXED_INTEGRAL(time_t, TimeT); break; case eLongValue: dcArgLongLong(call->vm, dcbArgLongLong(args)); break; case eShortValue: { short arg = dcbArgShort(args); if (isVarArgs) dcArgPointer(call->vm, (void*)(ptrdiff_t)arg); else dcArgShort(call->vm, arg); } break; case eBooleanValue: case eByteValue: { char arg = dcbArgChar(args); if (isVarArgs) dcArgPointer(call->vm, (void*)(ptrdiff_t)arg); else dcArgChar(call->vm, arg); } break; case eFloatValue: { float arg = dcbArgFloat(args); if (isVarArgs) dcArgDouble(call->vm, arg); else dcArgFloat(call->vm, arg); } break; case eDoubleValue: dcArgDouble(call->vm, dcbArgDouble(args)); break; case ePointerValue: { void* ptr = dcbArgPointer(args); jobject callIO = call && call->pCallIOs ? *(call->pCallIOs++) : NULL; if (toJava) { ptr = createPointerFromIO(env, ptr, callIO); } else { ptr = ptr ? getPointerPeer(env, ptr) : NULL; // printf("ARG POINTER = %d\n", ptr); } dcArgPointer(call->vm, ptr); } break; case eWCharValue: switch (sizeof(wchar_t)) { case 1: dcArgChar(call->vm, dcbArgChar(args)); break; case 2: dcArgShort(call->vm, dcbArgShort(args)); break; case 4: dcArgInt(call->vm, dcbArgInt(args)); break; default: throwException(env, "Invalid wchar_t size for argument !"); return JNI_FALSE; } break; case eEllipsis: { if (toJava) { throwException(env, "Calling Java ellipsis is not supported yet !"); return JNI_FALSE; } else { jobjectArray arr = (jobjectArray)dcbArgPointer(args); jsize n = (*env)->GetArrayLength(env, arr), i; for (i = 0; i < n; i++) { jobject arg = (*env)->GetObjectArrayElement(env, arr, i); #define TEST_INSTANCEOF(cl, st) \ if ((*env)->IsInstanceOf(env, arg, cl)) st; if (arg == NULL) dcArgPointer(call->vm, getPointerPeer(env, (void*)NULL)); else // As per the C standard for varargs, all ints are promoted to ptrdiff_t and float is promoted to double : TEST_INSTANCEOF(gIntClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)UnboxInt(env, arg))) else TEST_INSTANCEOF(gLongClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)UnboxLong(env, arg))) else TEST_INSTANCEOF(gShortClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)UnboxShort(env, arg))) else TEST_INSTANCEOF(gByteClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)UnboxByte(env, arg))) else TEST_INSTANCEOF(gBooleanClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)(char)UnboxBoolean(env, arg))) else TEST_INSTANCEOF(gCharClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)(short)UnboxChar(env, arg))) else TEST_INSTANCEOF(gDoubleClass, dcArgDouble(call->vm, UnboxDouble(env, arg))) else TEST_INSTANCEOF(gFloatClass, dcArgDouble(call->vm, UnboxFloat(env, arg))) else TEST_INSTANCEOF(gCLongClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)(long)UnboxCLong(env, arg))) else TEST_INSTANCEOF(gSizeTClass, dcArgPointer(call->vm, (void*)(ptrdiff_t)UnboxSizeT(env, arg))) else TEST_INSTANCEOF(gPointerClass, dcArgPointer(call->vm, getPointerPeer(env, (void*)arg))) else { throwException(env, "Invalid value type in ellipsis"); return JNI_FALSE; } } } break; } default: throwException(env, "Invalid argument value type !"); return JNI_FALSE; } } if ((*env)->ExceptionCheck(env)) return JNI_FALSE; return JNI_TRUE; }
jboolean followCallGenericJavaCallback(CallTempStruct* call, ValueType returnType, DCValue* result, void* callback) { JNIEnv* env = call->env; jobject ret = dcCallPointer(call->vm, callback); HACK_REFETCH_ENV(); if ((*env)->ExceptionCheck(env)) return JNI_FALSE; switch (returnType) { case eIntValue: result->i = UnboxInt(env, ret); break; case eLongValue: result->l = UnboxLong(env, ret); break; case eShortValue: result->s = UnboxShort(env, ret); break; case eByteValue: result->c = UnboxByte(env, ret); break; case eFloatValue: result->f = UnboxFloat(env, ret); break; case eDoubleValue: result->d = UnboxDouble(env, ret); break; case eBooleanValue: result->c = UnboxBoolean(env, ret); break; #define RETURN_UNBOXED_INTEGRAL(type, capitalized) \ { \ jlong v; \ if ((*env)->IsInstanceOf(env, ret, g ## capitalized ## Class)) \ v = Unbox ## capitalized(env, ret); \ else \ v = UnboxLong(env, ret); \ if (sizeof(type) == 4) \ result->i = (jint)v; \ else \ result->L = (jlong)v; \ } #define RETURN_BOXED_INTEGRAL(type, capitalized) \ { \ if ((*env)->IsInstanceOf(env, ret, g ## capitalized ##Class)) \ result->p = ret; \ else \ result->p = Box ## capitalized(env, (type)UnboxLong(env, ret)); \ } case eCLongValue: RETURN_UNBOXED_INTEGRAL(long, CLong) break; case eCLongObjectValue: RETURN_BOXED_INTEGRAL(long, CLong); break; case eSizeTValue: RETURN_UNBOXED_INTEGRAL(size_t, SizeT); break; case eSizeTObjectValue: RETURN_BOXED_INTEGRAL(size_t, SizeT); break; case eTimeTObjectValue: RETURN_BOXED_INTEGRAL(time_t, TimeT); break; case eVoidValue: assert(ret == NULL); break; case eIntFlagSet: result->i = (jint)getFlagValue(env, ret); break; case ePointerValue: result->p = ret ? getPointerPeer(env, (void*)ret) : NULL; call->pCallIOs++; break; case eWCharValue: switch (sizeof(wchar_t)) { case 1: result->c = (char)UnboxChar(env, ret); break; case 2: result->s = (short)UnboxChar(env, ret); break; case 4: result->i = UnboxInt(env, ret); break; default: throwException(env, "Invalid wchar_t size !"); return JNI_FALSE; } break; default: throwException(env, "Invalid return value type !"); return JNI_FALSE; } return JNI_TRUE; }