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; }
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; }