Ejemplo n.º 1
0
int
call_external_function(const char *funcname, const MincValue arglist[],
	const int nargs, MincValue *return_value)
{
	int result, numArgs = nargs;
	Arg retval;

	Arg *rtcmixargs = new Arg[nargs];
	if (rtcmixargs == NULL)
		return MEMORY_ERROR;

	// Convert arglist for passing to RTcmix function.
	for (int i = 0; i < nargs; i++) {
		switch (arglist[i].dataType()) {
		case MincFloatType:
			rtcmixargs[i] = (MincFloat)arglist[i];
			break;
		case MincStringType:
			rtcmixargs[i] = (MincString)arglist[i];
			break;
		case MincHandleType:
			rtcmixargs[i] = (Handle) (MincHandle)arglist[i];
#ifdef EMBEDDED
			if ((Handle)rtcmixargs[i] == NULL) {
				minc_die("can't pass a null handle (arg %d) to RTcmix function %s()", i, funcname);
				return PARAM_ERROR;
			}
#endif
			break;
		case MincListType:
			{
			MincList *list = (MincList *)arglist[i];
			if (list == NULL) {
				minc_die("can't pass a null list (arg %d) to RTcmix function %s()", i, funcname);
				return PARAM_ERROR;
			}
			if (list->len <= 0) {
				minc_die("can't pass an empty list (arg %d) to RTcmix function %s()", i, funcname);
				return PARAM_ERROR;
			}
			// If list is final argument to function, treat its contents as additional function arguments
			if (i == nargs-1) {
				int argCount = i;
				Arg *newargs = minc_list_to_arglist(funcname, list->data, list->len, rtcmixargs, &argCount);
				delete [] rtcmixargs;
				if (newargs == NULL)
					return -1;
				rtcmixargs = newargs;
				numArgs = argCount;
			}
			// If list contains only floats, convert and pass it along.
			else {
				Array *newarray = (Array *) emalloc(sizeof(Array));
				if (newarray == NULL)
					return MEMORY_ERROR;
				assert(sizeof(*newarray->data) == sizeof(double));	// because we cast MincFloat to double here
				newarray->data = (double *) float_list_to_array(list);
				if (newarray->data != NULL) {
					newarray->len = list->len;
					rtcmixargs[i] = newarray;
				}
				else {
					minc_die("can't pass a mixed-type list (arg %d) to RTcmix function %s()", i, funcname);
					free(newarray);
					return PARAM_ERROR;
				}
			}
			}
			break;
		default:
			minc_die("call_external_function: %s(): arg %d: invalid argument type",
					 funcname, i);
			return PARAM_ERROR;
			break;
		}
	}

	result = RTcmix::dispatch(funcname, rtcmixargs, numArgs, &retval);
   
	// Convert return value from RTcmix function.
	switch (retval.type()) {
	case DoubleType:
		*return_value = (MincFloat) retval;
		break;
	case StringType:
		*return_value = (MincString) retval;
		break;
	case HandleType:
		*return_value = (MincHandle) (Handle) retval;
		break;
	case ArrayType:
#ifdef NOMORE
// don't think functions will return non-opaque arrays to Minc, but if they do,
// these should be converted to MincListType
		return_value->type = MincArrayType;
		{
			Array *array = (Array *) retval;
			return_value->val.array.len = array->len;
			return_value->val.array.data = array->data;
		}
#endif
		break;
	default:
		break;
	}

	delete [] rtcmixargs;

	return result;
}
Ejemplo n.º 2
0
int
call_external_function(const char *funcname, const MincListElem arglist[],
	const int nargs, MincListElem *return_value)
{
	int i, result;
	Arg retval;

	Arg *rtcmixargs = new Arg[nargs];
	if (rtcmixargs == NULL)
		return -1;

	// Convert arglist for passing to RTcmix function.
	for (i = 0; i < nargs; i++) {
		switch (arglist[i].type) {
		case MincFloatType:
			rtcmixargs[i] = arglist[i].val.number;
			break;
		case MincStringType:
			rtcmixargs[i] = arglist[i].val.string;
			break;
		case MincHandleType:
			rtcmixargs[i] = (Handle) arglist[i].val.handle;
			break;
		case MincListType:
			// If list contains only floats, convert and pass it along.
			// Otherwise, it's an error.
			{
				Array *newarray = (Array *) emalloc(sizeof(Array));
				if (newarray == NULL)
					return -1;
				assert(sizeof(*newarray->data) == sizeof(double));	// because we cast MincFloat to double here
				newarray->data = (double *) float_list_to_array(arglist[i].val.list);
				if (newarray->data != NULL) {
					newarray->len = arglist[i].val.list->len;
					rtcmixargs[i] = newarray;
				}
				else {
					minc_die("can't pass an empty or mixed-type list to RTcmix function %s()", funcname);
					free(newarray);
					return -1;
				}
			}
			break;
		default:
			minc_die("call_external_function: %s(): invalid argument type",
					 funcname);
			return -1;
			break;
		}
	}

	result = RTcmix::dispatch(funcname, rtcmixargs, nargs, &retval);
   
	// Convert return value from RTcmix function.
	switch (retval.type()) {
	case DoubleType:
		return_value->type = MincFloatType;
		return_value->val.number = (MincFloat) retval;
		break;
	case StringType:
		return_value->type = MincStringType;
		return_value->val.string = (MincString) retval;
		break;
	case HandleType:
		return_value->type = MincHandleType;
		return_value->val.handle = (MincHandle) (Handle) retval;
		if (return_value->val.handle) {
			ref_handle(return_value->val.handle);
		}
		break;
	case ArrayType:
#ifdef NOMORE
// don't think functions will return non-opaque arrays to Minc, but if they do,
// these should be converted to MincListType
		return_value->type = MincArrayType;
		{
			Array *array = (Array *) retval;
			return_value->val.array.len = array->len;
			return_value->val.array.data = array->data;
		}
#endif
		break;
	default:
		break;
	}

	delete [] rtcmixargs;

	return result;
}