Example #1
0
char cbHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata)
{
  int* ud = (int*)userdata;
  int       arg1 = dcbArgInt     (args);
  float     arg2 = dcbArgFloat   (args);
  short     arg3 = dcbArgShort   (args);
  double    arg4 = dcbArgDouble  (args);
  long long arg5 = dcbArgLongLong(args);

  printf("reached callback\n");
  printf("userdata (should be 1337): %d\n", *ud);
  printf("1st argument (should be  123): %d\n", arg1);
  printf("2nd argument (should be 23.f): %f\n", arg2);
  printf("3rd argument (should be    3): %d\n", arg3);
  printf("4th argument (should be 1.82): %f\n", arg4);
  printf("5th argument (should be 9909): %lld\n", arg5);

  if(*ud == 1337) *ud = 1;
  if(arg1 ==  123) ++*ud;
  if(arg2 == 23.f) ++*ud;
  if(arg3 ==    3) ++*ud;
  if(arg4 == 1.82) ++*ud;
  if(arg5 == 9909) ++*ud;

  result->s = 1234;
  return 's';
}
Example #2
0
char handler(DCCallback* that, DCArgs* input, DCValue* output, void* userdata)
{
  const char* signature = (const char*) userdata;
  int pos = 0; 
  char ch;

  signature = SignatureSkipCallPrefix(signature);

  for(;;) {
    ch = *signature++;
    if (ch == DC_SIGCHAR_ENDARG) break;
    Args[pos].L = 0xDEADC0DECAFEBABELL;
    switch(ch) {
      case DC_SIGCHAR_BOOL:     Args[pos].B = dcbArgBool     (input); break;
      case DC_SIGCHAR_CHAR:     Args[pos].c = dcbArgChar     (input); break;
      case DC_SIGCHAR_UCHAR:    Args[pos].C = dcbArgUChar    (input); break;
      case DC_SIGCHAR_SHORT:    Args[pos].s = dcbArgShort    (input); break;
      case DC_SIGCHAR_USHORT:   Args[pos].S = dcbArgUShort   (input); break;
      case DC_SIGCHAR_INT:      Args[pos].i = dcbArgInt      (input); break;
      case DC_SIGCHAR_UINT:     Args[pos].I = dcbArgUInt     (input); break;
      case DC_SIGCHAR_LONG:     Args[pos].j = dcbArgLong     (input); break;
      case DC_SIGCHAR_ULONG:    Args[pos].J = dcbArgULong    (input); break;
      case DC_SIGCHAR_LONGLONG: Args[pos].l = dcbArgLongLong (input); break;
      case DC_SIGCHAR_ULONGLONG:Args[pos].L = dcbArgULongLong(input); break;
      case DC_SIGCHAR_FLOAT:    Args[pos].f = dcbArgFloat    (input); break; 
      case DC_SIGCHAR_DOUBLE:   Args[pos].d = dcbArgDouble   (input); break;
      case DC_SIGCHAR_POINTER:  Args[pos].p = dcbArgPointer  (input); break;
    }
    ++pos;
  }

  ch = *signature++;

  /* currently, no void result is supported by the suite */
  GetReferenceResult(output, ch);

  switch(ch) {
    case DC_SIGCHAR_BOOL:     return 'B';
    case DC_SIGCHAR_CHAR:     return 'c';
    case DC_SIGCHAR_UCHAR:    return 'C';
    case DC_SIGCHAR_SHORT:    return 's';
    case DC_SIGCHAR_USHORT:   return 'S';
    case DC_SIGCHAR_INT:      return 'i';
    case DC_SIGCHAR_UINT:     return 'I';
    case DC_SIGCHAR_LONG:     return 'j'; 
    case DC_SIGCHAR_ULONG:    return 'J'; 
    case DC_SIGCHAR_LONGLONG: return 'l';
    case DC_SIGCHAR_ULONGLONG:return 'l';
    case DC_SIGCHAR_FLOAT:    return 'f';
    case DC_SIGCHAR_DOUBLE:   return 'd';
    case DC_SIGCHAR_POINTER:  return 'p';
    default: assert(0); return 'v';
  }
}
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;
}
Example #4
0
static char callback_handler(DCCallback *cb, DCArgs *cb_args, DCValue *cb_result, MVMNativeCallback *data) {
    CallbackInvokeData cid;
    MVMint32 num_roots, i;
    MVMRegister res;

    /* Build a callsite and arguments buffer. */
    MVMThreadContext *tc = data->tc;
    MVMRegister *args = MVM_malloc(data->num_types * sizeof(MVMRegister));
    num_roots = 0;
    for (i = 1; i < data->num_types; i++) {
        MVMObject *type     = data->types[i];
        MVMint16   typeinfo = data->typeinfos[i];
        switch (typeinfo & MVM_NATIVECALL_ARG_TYPE_MASK) {
            case MVM_NATIVECALL_ARG_CHAR:
                args[i - 1].i64 = dcbArgChar(cb_args);
                break;
            case MVM_NATIVECALL_ARG_SHORT:
                args[i - 1].i64 = dcbArgShort(cb_args);
                break;
            case MVM_NATIVECALL_ARG_INT:
                args[i - 1].i64 = dcbArgInt(cb_args);
                break;
            case MVM_NATIVECALL_ARG_LONG:
                args[i - 1].i64 = dcbArgLong(cb_args);
                break;
            case MVM_NATIVECALL_ARG_LONGLONG:
                args[i - 1].i64 = dcbArgLongLong(cb_args);
                break;
            case MVM_NATIVECALL_ARG_FLOAT:
                args[i - 1].n64 = dcbArgFloat(cb_args);
                break;
            case MVM_NATIVECALL_ARG_DOUBLE:
                args[i - 1].n64 = dcbArgDouble(cb_args);
                break;
            case MVM_NATIVECALL_ARG_ASCIISTR:
            case MVM_NATIVECALL_ARG_UTF8STR:
            case MVM_NATIVECALL_ARG_UTF16STR:
                args[i - 1].o = MVM_nativecall_make_str(tc, type, typeinfo,
                    (char *)dcbArgPointer(cb_args));
                MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o));
                num_roots++;
                break;
            case MVM_NATIVECALL_ARG_CSTRUCT:
                args[i - 1].o = MVM_nativecall_make_cstruct(tc, type,
                    dcbArgPointer(cb_args));
                MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o));
                num_roots++;
                break;
            case MVM_NATIVECALL_ARG_CPOINTER:
                args[i - 1].o = MVM_nativecall_make_cpointer(tc, type,
                    dcbArgPointer(cb_args));
                MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o));
                num_roots++;
                break;
            case MVM_NATIVECALL_ARG_CARRAY:
                args[i - 1].o = MVM_nativecall_make_carray(tc, type,
                    dcbArgPointer(cb_args));
                MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o));
                num_roots++;
                break;
            case MVM_NATIVECALL_ARG_CUNION:
                args[i - 1].o = MVM_nativecall_make_cunion(tc, type,
                    dcbArgPointer(cb_args));
                MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o));
                num_roots++;
                break;
            case MVM_NATIVECALL_ARG_CALLBACK:
                /* TODO: A callback -return- value means that we have a C method
                * that needs to be wrapped similarly to a is native(...) Perl 6
                * sub. */
                dcbArgPointer(cb_args);
                args[i - 1].o = type;
                MVM_gc_root_temp_push(tc, (MVMCollectable **)&(args[i - 1].o));
                num_roots++;
            case MVM_NATIVECALL_ARG_UCHAR:
                args[i - 1].i64 = dcbArgUChar(cb_args);
                break;
            case MVM_NATIVECALL_ARG_USHORT:
                args[i - 1].i64 = dcbArgUShort(cb_args);
                break;
            case MVM_NATIVECALL_ARG_UINT:
                args[i - 1].i64 = dcbArgUInt(cb_args);
                break;
            case MVM_NATIVECALL_ARG_ULONG:
                args[i - 1].i64 = dcbArgULong(cb_args);
                break;
            case MVM_NATIVECALL_ARG_ULONGLONG:
                args[i - 1].i64 = dcbArgULongLong(cb_args);
                break;
            default:
                MVM_exception_throw_adhoc(tc,
                    "Internal error: unhandled dyncall callback argument type");
        }
    }

    /* Call into a nested interpreter (since we already are in one). Need to
     * save a bunch of state around each side of this. */
    cid.invokee = data->target;
    cid.args    = args;
    cid.cs      = data->cs;
    {
        MVMuint8 **backup_interp_cur_op         = tc->interp_cur_op;
        MVMuint8 **backup_interp_bytecode_start = tc->interp_bytecode_start;
        MVMRegister **backup_interp_reg_base    = tc->interp_reg_base;
        MVMCompUnit **backup_interp_cu          = tc->interp_cu;
        MVMFrame *backup_cur_frame              = tc->cur_frame;
        MVMFrame *backup_thread_entry_frame     = tc->thread_entry_frame;
        MVMuint32 backup_mark                   = MVM_gc_root_temp_mark(tc);
        jmp_buf backup_interp_jump;
        memcpy(backup_interp_jump, tc->interp_jump, sizeof(jmp_buf));

        tc->cur_frame->return_value = &res;
        tc->cur_frame->return_type  = MVM_RETURN_OBJ;
        MVM_interp_run(tc, &callback_invoke, &cid);

        tc->interp_cur_op         = backup_interp_cur_op;
        tc->interp_bytecode_start = backup_interp_bytecode_start;
        tc->interp_reg_base       = backup_interp_reg_base;
        tc->interp_cu             = backup_interp_cu;
        tc->cur_frame             = backup_cur_frame;
        tc->thread_entry_frame    = backup_thread_entry_frame;
        memcpy(tc->interp_jump, backup_interp_jump, sizeof(jmp_buf));
        MVM_gc_root_temp_mark_reset(tc, backup_mark);
    }

    /* Handle return value. */
    if (res.o) {
        MVMContainerSpec const *contspec = STABLE(res.o)->container_spec;
        if (contspec && contspec->fetch_never_invokes)
            contspec->fetch(data->tc, res.o, &res);
    }
    switch (data->typeinfos[0] & MVM_NATIVECALL_ARG_TYPE_MASK) {
        case MVM_NATIVECALL_ARG_VOID:
            break;
        case MVM_NATIVECALL_ARG_CHAR:
            cb_result->c = MVM_nativecall_unmarshal_char(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_SHORT:
            cb_result->s = MVM_nativecall_unmarshal_short(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_INT:
            cb_result->i = MVM_nativecall_unmarshal_int(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_LONG:
            cb_result->j = MVM_nativecall_unmarshal_long(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_LONGLONG:
            cb_result->l = MVM_nativecall_unmarshal_longlong(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_FLOAT:
            cb_result->f = MVM_nativecall_unmarshal_float(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_DOUBLE:
            cb_result->d = MVM_nativecall_unmarshal_double(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_ASCIISTR:
        case MVM_NATIVECALL_ARG_UTF8STR:
        case MVM_NATIVECALL_ARG_UTF16STR:
            cb_result->Z = MVM_nativecall_unmarshal_string(data->tc, res.o, data->typeinfos[0], NULL);
            break;
        case MVM_NATIVECALL_ARG_CSTRUCT:
            cb_result->p = MVM_nativecall_unmarshal_cstruct(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_CPOINTER:
            cb_result->p = MVM_nativecall_unmarshal_cpointer(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_CARRAY:
            cb_result->p = MVM_nativecall_unmarshal_carray(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_CUNION:
            cb_result->p = MVM_nativecall_unmarshal_cunion(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_VMARRAY:
            cb_result->p = MVM_nativecall_unmarshal_vmarray(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_CALLBACK:
            cb_result->p = unmarshal_callback(data->tc, res.o, data->types[0]);
            break;
        case MVM_NATIVECALL_ARG_UCHAR:
            cb_result->c = MVM_nativecall_unmarshal_uchar(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_USHORT:
            cb_result->s = MVM_nativecall_unmarshal_ushort(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_UINT:
            cb_result->i = MVM_nativecall_unmarshal_uint(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_ULONG:
            cb_result->j = MVM_nativecall_unmarshal_ulong(data->tc, res.o);
            break;
        case MVM_NATIVECALL_ARG_ULONGLONG:
            cb_result->l = MVM_nativecall_unmarshal_ulonglong(data->tc, res.o);
            break;
        default:
            MVM_exception_throw_adhoc(data->tc,
                "Internal error: unhandled dyncall callback return type");
    }

    /* Clean up. */
    MVM_gc_root_temp_pop_n(tc, num_roots);
    MVM_free(args);

    /* Indicate what we're producing as a result. */
    return get_signature_char(data->typeinfos[0]);
}
Example #5
0
DCushort    dcbArgUShort   (DCArgs* p) {
    return (DCushort)   dcbArgShort(p);
}
jboolean followArgsGenericJavaCallback(CallTempStruct* call, DCArgs* args, int nTypes, ValueType* pTypes) 
{	
	JNIEnv* env = call->env;
	int iParam;
	jobjectArray arr = (*env)->NewObjectArray(env, nTypes, gObjectClass, NULL);
	
	for (iParam = 0; iParam < nTypes; iParam++) {
		ValueType type = pTypes[iParam];
		jobject arg = NULL;
		switch (type) {
			case eIntFlagSet:
				arg = BoxInt(env, (jint)getFlagValue(env, (jobject)dcbArgPointer(args)));
				break;
			case eIntValue:
				arg = BoxInt(env, dcbArgInt(args));
				break;
			case eCLongValue: {
				jlong v;
				if (sizeof(long) == 4)
					v = dcbArgLong(args);
				else
					v = dcbArgLongLong(args);
				arg = BoxCLong(env, v);
				break;
			}
			case eSizeTValue: {
				jlong v;
				if (sizeof(size_t) == 4)
					v = dcbArgInt(args);
				else
					v = dcbArgLongLong(args);
				arg = BoxSizeT(env, v);
				break;
			}
			case eLongValue:
				arg = BoxLong(env, dcbArgLongLong(args));
				break;
			case eShortValue:
				arg = BoxShort(env, dcbArgShort(args));
				break;
			case eBooleanValue:
			case eByteValue:
				arg = BoxByte(env, dcbArgChar(args));
				break;
			case eFloatValue:
				arg = BoxFloat(env, dcbArgFloat(args));
				break;
			case eDoubleValue:
				arg = BoxDouble(env, dcbArgDouble(args));
				break;
			case ePointerValue:
				{
					jobject callIO = call && call->pCallIOs ? *(call->pCallIOs++) : NULL;
					void* ptr = dcbArgPointer(args);
					arg = createPointerFromIO(env, ptr, callIO);
				}
				break;
			case eWCharValue:
				switch (sizeof(wchar_t)) {
				case 1:
					arg = BoxChar(env, dcbArgChar(args));
					break;
				case 2:
					arg = BoxChar(env, dcbArgShort(args));
					break;
				case 4:
					arg = BoxInt(env, dcbArgInt(args));
					break;
				default:
					throwException(env, "Invalid wchar_t size for argument !");
					return JNI_FALSE;
				}
				break;
			default:
				throwException(env, "Invalid argument value type !");
				return JNI_FALSE;
			
		}
		(*env)->SetObjectArrayElement(env, arr, iParam, arg);
	}
	dcArgPointer(call->vm, arr);
	
	if ((*env)->ExceptionCheck(env))
		return JNI_FALSE;
	return JNI_TRUE;
}