VALUE or_feval(VALUE function_name, VALUE arguments) { VALUE ruby_val = Qnil; int i, n; octave_value_list argList; n = RARRAY_LEN(arguments); bool is_function_definition = (n == 1 && FIXNUM_P(RARRAY_PTR(arguments)[0]) == 0 && strncmp(RSTRING_PTR(StringValue(RARRAY_PTR(arguments)[0])), "function ", 9) == 0); for (i = 0; i < n; i++) { argList(i) = OR_Variable(RARRAY_PTR(arguments)[i]).to_octave(); } if (octave_set_current_context) { // unwind_protect::run_all(); raw_mode(0); } can_interrupt = true; octave_initialized = true; try { symbol_table::set_scope(symbol_table::top_scope()); reset_error_handler(); int nargout = (is_function_definition ? 0 : 1); octave_value_list val = feval(std::string(RSTRING_PTR(function_name)), argList, nargout); if(val.length() > 0 && val(0).is_defined()) { ruby_val = OR_Variable(val(0)).to_ruby(); } } catch (octave_interrupt_exception) { recover_from_exception(); error_state = -2; } catch (std::bad_alloc) { recover_from_exception(); error_state = -3; } octave_initialized = false; return(ruby_val); }
int octave_call(const char *string) { int parse_status; octave_save_signal_mask (); if (octave_set_current_context) { #if defined (USE_EXCEPTIONS_FOR_INTERRUPTS) panic_impossible (); #else unwind_protect::run_all (); raw_mode (0); std::cout << "\n"; octave_restore_signal_mask (); #endif } can_interrupt = true; octave_catch_interrupts (); octave_initialized = true; // XXX FIXME XXX need to give caller an opaque pointer // so that they can define and use separate namespaces // when calling octave, with a shared global namespace. // Something like: // int call_octave (const char *string, void *psymtab = NULL) { // ... // curr_sym_tab = psymtab == NULL ? top_level_sym_tab : symbol_table; // I suppose to be safe from callbacks (surely we have to // provide some way to call back from embedded octave into // the user's application), we should push and pop the current // symbol table. // Note that I'm trying to distinguish exception from // failure in the return codes. I believe failure is // indicated by -1. I have execution exception (including // user interrupt and more dramatic failures) returning -2 // and memory failure returning -3. We should formalize // this with error codes defined in embed_octave.h. Maybe // a more fine-grained approach could be used within octave // proper. try { curr_sym_tab = top_level_sym_tab; reset_error_handler (); eval_string(string, false, parse_status); } catch (octave_interrupt_exception) { recover_from_exception (); std::cout << "\n"; error_state = -2; } catch (std::bad_alloc) { recover_from_exception (); std::cout << "\n"; error_state = -3; } octave_restore_signal_mask(); octave_initialized = false; // XXX FIXME XXX callbacks calling embed_octave // may or may not want error_state reset. return error_state; }
bool COctaveInterface::run_octave_helper(CSGInterface* from_if) { from_if->SG_DEBUG("Entering Octave\n"); octave_save_signal_mask (); if (octave_set_current_context) { #if defined (USE_EXCEPTIONS_FOR_INTERRUPTS) panic_impossible (); #else unwind_protect::run_all (); raw_mode (0); octave_restore_signal_mask (); #endif } can_interrupt = true; octave_catch_interrupts (); octave_initialized = true; try { int parse_status; char* octave_code=NULL; clear_octave_globals(); for (int i=0; i<from_if->get_nrhs(); i++) { int len=0; char* var_name = from_if->get_string(len); from_if->SG_DEBUG("var_name = '%s'\n", var_name); if (strmatch(var_name, "octavecode")) { len=0; octave_code=from_if->get_string(len); from_if->SG_DEBUG("octave_code = '%s'\n", octave_code); break; } else { octave_value_list args; COctaveInterface* in = new COctaveInterface(args, 1, false); in->create_return_values(1); from_if->translate_arg(from_if, in); #if OCTAVE_APIVERSION >= 37 symbol_table::varref (var_name) = in->get_return_values()(0); #else set_global_value(var_name, in->get_return_values()(0)); #endif delete[] var_name; SG_UNREF(in); } } #if OCTAVE_APIVERSION >= 37 #else symbol_table* old=curr_sym_tab; curr_sym_tab = global_sym_tab; #endif reset_error_handler (); eval_string(octave_code, false, parse_status); delete[] octave_code; int32_t sz=0; octave_value_list results; #if OCTAVE_APIVERSION >= 37 if (symbol_table::is_variable("results")) { results = symbol_table::varval("results"); //results = get_global_value("results", false); sz=results.length(); } #else if (curr_sym_tab->lookup("results")) { results = get_global_value("results", false); sz=results.length(); } #endif if (sz>0) { if (results(0).is_list()) { from_if->SG_DEBUG("Found return list of length %d\n", results(0).length()); results=results(0).list_value(); sz=results.length(); } } if (sz>0 && from_if->create_return_values(sz)) { from_if->SG_DEBUG("Found %d args\n", sz); COctaveInterface* out = new COctaveInterface(results, sz, false); //process d for (int32_t i=0; i<sz; i++) from_if->translate_arg(out, from_if); SG_UNREF(out); } else { if (sz!=from_if->get_nlhs()) { from_if->SG_ERROR("Number of return values (%d) does not match number of expected" " return values (%d).\n", sz, from_if->get_nlhs()); } } #if OCTAVE_APIVERSION >= 37 #else curr_sym_tab=old; #endif } catch (octave_interrupt_exception) { recover_from_exception (); SG_SPRINT("%\n"); } catch (std::bad_alloc) { recover_from_exception (); SG_SPRINT("%\n"); } octave_restore_signal_mask(); octave_initialized = false; from_if->SG_DEBUG("Leaving Octave.\n"); return true; }