Home | History | Annotate | Download | only in octave
      1 %insert(runtime) %{
      2 #include <cstdlib>
      3 #include <iostream>
      4 #include <octave/oct.h>
      5 #include <octave/Cell.h>
      6 #include <octave/dynamic-ld.h>
      7 #include <octave/oct-env.h>
      8 #include <octave/oct-map.h>
      9 #include <octave/ov-fcn-handle.h>
     10 #include <octave/parse.h>
     11 #include <octave/toplev.h>
     12 #include <octave/unwind-prot.h>
     13 %}
     14 
     15 %insert(runtime) "swigrun.swg";
     16 %insert(runtime) "swigerrors.swg";
     17 %insert(runtime) "octrun.swg";
     18 
     19 %insert(initbeforefunc) "swiginit.swg"
     20 
     21 %insert(initbeforefunc) %{
     22 
     23 static bool SWIG_init_user(octave_swig_type* module_ns);
     24 
     25 SWIGINTERN bool SWIG_Octave_LoadModule(std::string name) {
     26   bool retn;
     27   {
     28 #if OCTAVE_API_VERSION_NUMBER < 38
     29     unwind_protect::begin_frame("SWIG_Octave_LoadModule");
     30     unwind_protect_int(error_state);
     31     unwind_protect_int(warning_state);
     32     unwind_protect_bool(discard_error_messages);
     33     unwind_protect_bool(discard_warning_messages);
     34 #else
     35     unwind_protect frame;
     36     frame.protect_var(error_state);
     37     frame.protect_var(warning_state);
     38     frame.protect_var(discard_error_messages);
     39     frame.protect_var(discard_warning_messages);
     40 #endif
     41     error_state = 0;
     42     warning_state = 0;
     43     discard_error_messages = true;
     44     discard_warning_messages = true;
     45     feval(name, octave_value_list(), 0);
     46     retn = (error_state == 0);
     47 #if OCTAVE_API_VERSION_NUMBER < 38
     48     unwind_protect::run_frame("SWIG_Octave_LoadModule");
     49 #endif
     50   }
     51   if (!retn) {
     52     error(SWIG_name_d ": could not load module `%s'", name.c_str());
     53   }
     54   return retn;
     55 }
     56 
     57 SWIGINTERN bool SWIG_Octave_InstallFunction(octave_function *octloadfcn, std::string name) {
     58   bool retn;
     59   {
     60 #if OCTAVE_API_VERSION_NUMBER < 38
     61     unwind_protect::begin_frame("SWIG_Octave_InstallFunction");
     62     unwind_protect_int(error_state);
     63     unwind_protect_int(warning_state);
     64     unwind_protect_bool(discard_error_messages);
     65     unwind_protect_bool(discard_warning_messages);
     66 #else
     67     unwind_protect frame;
     68     frame.protect_var(error_state);
     69     frame.protect_var(warning_state);
     70     frame.protect_var(discard_error_messages);
     71     frame.protect_var(discard_warning_messages);
     72 #endif
     73     error_state = 0;
     74     warning_state = 0;
     75     discard_error_messages = true;
     76     discard_warning_messages = true;
     77     octave_value_list args;
     78     args.append(name);
     79     args.append(octloadfcn->fcn_file_name());
     80     error_state = 0;
     81     feval("autoload", args, 0);
     82     retn = (error_state == 0);
     83 #if OCTAVE_API_VERSION_NUMBER < 38
     84     unwind_protect::run_frame("SWIG_Octave_InstallFunction");
     85 #endif
     86   }
     87   if (!retn) {
     88     error(SWIG_name_d ": could not load function `%s'", name.c_str());
     89   }
     90   return retn;
     91 }
     92 
     93 static const char *const subclass_usage = "-*- texinfo -*- \n\
     94 @deftypefn {Loadable Function} {} subclass()\n\
     95 @deftypefnx{Loadable Function} {} subclass(@var{swigclass}, @var{name}, @var{fcn}, @dots{})\n\
     96 Subclass a C++ class from within Octave, and provide implementations of its virtual methods.\n\
     97 \n\
     98 See the SWIG manual for usage examples.\n\
     99 @end deftypefn";
    100 
    101 DEFUN_DLD( subclass, args, nargout, subclass_usage ) {
    102   octave_swig_type *top = new octave_swig_type;
    103   for (int j = 0; j < args.length(); ++j) {
    104     if (args(j).type_id() == octave_swig_ref::static_type_id()) {
    105       octave_swig_ref *osr = static_cast < octave_swig_ref *>(args(j).internal_rep());
    106       octave_swig_type *ost = osr->get_ptr();
    107       if (!ost->is_owned()) {
    108         error("subclass: cannot subclass object not constructed on octave side");
    109         return octave_value_list();
    110       }
    111       top->merge(*ost);
    112     } else if (args(j).is_function_handle()) {
    113       top->assign(args(j).fcn_handle_value()->fcn_name(), args(j));
    114     } else if (args(j).is_string()) {
    115       if (j + 1 >= args.length()) {
    116         error("subclass: member assignments must be of string,value form");
    117         return octave_value_list();
    118       }
    119       top->assign(args(j).string_value(), args(j + 1));
    120       ++j;
    121     } else {
    122       error("subclass: invalid arguments to subclass()");
    123       return octave_value_list();
    124     }
    125   }
    126   return octave_value(Swig::swig_value_ref(top));
    127 }
    128 
    129 static const char *const swig_type_usage = "-*- texinfo -*- \n\
    130 @deftypefn {Loadable Function} {} swig_type(@var{swigref})\n\
    131 Return the underlying C/C++ type name of a SWIG-wrapped object.\n\
    132 @end deftypefn";
    133 
    134 DEFUN_DLD( swig_type, args, nargout, swig_type_usage ) {
    135   if (args.length() != 1) {
    136     error("swig_type: must be called with only a single object");
    137     return octave_value_list();
    138   }
    139   octave_swig_type *ost = Swig::swig_value_deref(args(0));
    140   if (!ost) {
    141     error("swig_type: object is not a swig_ref");
    142     return octave_value_list();
    143   }
    144   return octave_value(ost->swig_type_name());
    145 }
    146 
    147 static const char *const swig_typequery_usage = "-*- texinfo -*- \n\
    148 @deftypefn {Loadable Function} {} swig_typequery(@var{string})\n\
    149 Return @var{string} if it is a recognised SWIG-wrapped C/C++ type name;\n\
    150 otherwise return `<unknown>'.\n\
    151 @end deftypefn";
    152 
    153 DEFUN_DLD( swig_typequery, args, nargout, swig_typequery_usage ) {
    154   if (args.length() != 1 || !args(0).is_string()) {
    155     error("swig_typequery: must be called with single string argument");
    156     return octave_value_list();
    157   }
    158   swig_module_info *module = SWIG_GetModule(0);
    159   swig_type_info *type = SWIG_TypeQueryModule(module, module, args(0).string_value().c_str());
    160   if (!type)
    161     return octave_value("<unknown>");
    162   return octave_value(type->name);
    163 }
    164 
    165 static const char *const swig_this_usage = "-*- texinfo -*- \n\
    166 @deftypefn {Loadable Function} {} swig_this(@var{swigref})\n\
    167 Return the underlying C/C++ pointer of a SWIG-wrapped object.\n\
    168 @end deftypefn";
    169 
    170 DEFUN_DLD( swig_this, args, nargout, swig_this_usage ) {
    171   if (args.length() != 1) {
    172     error("swig_this: must be called with only a single object");
    173     return octave_value_list();
    174   }
    175   if (args(0).is_matrix_type() && args(0).rows() == 0 && args(0).columns() == 0)
    176     return octave_value(octave_uint64(0));
    177   octave_swig_type *ost = Swig::swig_value_deref(args(0));
    178   if (!ost) {
    179     error("swig_this: object is not a swig_ref");
    180     return octave_value_list();
    181   }
    182   return octave_value(octave_uint64((unsigned long long) ost->swig_this()));
    183 }
    184 
    185 static const char *const SWIG_name_usage = "-*- texinfo -*- \n\
    186 @deftypefn {Loadable Module} {} " SWIG_name_d "\n\
    187 Loads the SWIG-generated module `" SWIG_name_d "'.\n\
    188 @end deftypefn";
    189 
    190 DEFUN_DLD( SWIG_name, args, nargout, SWIG_name_usage ) {
    191 
    192   static octave_swig_type* module_ns = 0;
    193 
    194   // workaround to prevent octave seg-faulting on exit: set Octave exit function
    195   // octave_exit to _Exit, which exits immediately without trying to cleanup memory.
    196   // definitely affects version 3.2.*, not sure about 3.3.*, seems to be fixed in
    197   // version 3.4.* and above. can be turned off with macro definition.
    198 #ifndef SWIG_OCTAVE_NO_SEGFAULT_HACK
    199 #if 36 < OCTAVE_API_VERSION_NUMBER && OCTAVE_API_VERSION_NUMBER < 45
    200   octave_exit = ::_Exit;
    201 #endif
    202 #endif
    203 
    204   // check for no input and output args
    205   if (args.length() != 0 || nargout != 0) {
    206     print_usage();
    207     return octave_value_list();
    208   }
    209 
    210   // create module on first function call
    211   if (!module_ns) {
    212 
    213     // workaround bug in octave where installing global variable of custom type and then
    214     // exiting without explicitly clearing the variable causes octave to segfault.
    215 #if OCTAVE_API_VERSION_NUMBER > 36
    216     octave_value_list eval_args;
    217     eval_args.append("base");
    218     eval_args.append("function __swig_atexit__; "
    219                      "  if mislocked() "
    220                      "    clear -all; "
    221                      "  else "
    222                      "    mlock(); "
    223                      "  endif; "
    224                      "endfunction; "
    225                      "__swig_atexit__; "
    226                      "atexit(\"__swig_atexit__\", false); "
    227                      "atexit(\"__swig_atexit__\")");
    228     feval("evalin", eval_args, 0);
    229 #endif
    230 
    231     octave_swig_ref::register_type();
    232     octave_swig_packed::register_type();
    233     SWIG_InitializeModule(0);
    234     SWIG_PropagateClientData();
    235 
    236     octave_function *me = octave_call_stack::current();
    237 
    238     if (!SWIG_Octave_InstallFunction(me, "swig_type")) {
    239       return octave_value_list();
    240     }
    241     if (!SWIG_Octave_InstallFunction(me, "swig_typequery")) {
    242       return octave_value_list();
    243     }
    244     if (!SWIG_Octave_InstallFunction(me, "swig_this")) {
    245       return octave_value_list();
    246     }
    247     if (!SWIG_Octave_InstallFunction(me, "subclass")) {
    248       return octave_value_list();
    249     }
    250 
    251     octave_swig_type* cvar_ns=0;
    252     if (std::string(SWIG_global_name) != ".") {
    253       cvar_ns=new octave_swig_type;
    254       for (int j=0;swig_globals[j].name;++j)
    255         if (swig_globals[j].get_method)
    256           cvar_ns->assign(swig_globals[j].name,&swig_globals[j]);
    257     }
    258 
    259     module_ns=new octave_swig_type(0, 0, 0, true);
    260     if (std::string(SWIG_global_name) != ".") {
    261       module_ns->assign(SWIG_global_name,Swig::swig_value_ref(cvar_ns));
    262     }
    263     else {
    264       for (int j=0;swig_globals[j].name;++j)
    265         if (swig_globals[j].get_method)
    266           module_ns->assign(swig_globals[j].name,&swig_globals[j]);
    267     }
    268     for (int j=0;swig_globals[j].name;++j)
    269       if (swig_globals[j].method)
    270         module_ns->assign(swig_globals[j].name,&swig_globals[j]);
    271 
    272     // * need better solution here; swig_type -> octave_class mapping is
    273     // * really n-to-1, in some cases such as template partial spec, etc.
    274     // * see failing tests.
    275     for (int j=0;swig_types[j];++j)
    276       if (swig_types[j]->clientdata) {
    277         swig_octave_class* c=(swig_octave_class*)swig_types[j]->clientdata;
    278         module_ns->assign(c->name,
    279                         Swig::swig_value_ref
    280                         (new octave_swig_type(0,swig_types[j])));
    281       }
    282 
    283     if (!SWIG_init_user(module_ns)) {
    284       delete module_ns;
    285       module_ns=0;
    286       return octave_value_list();
    287     }
    288 
    289     SWIG_InstallOps(octave_swig_ref::static_type_id());
    290 
    291     octave_swig_type::swig_member_const_iterator mb;
    292     for (mb = module_ns->swig_members_begin(); mb != module_ns->swig_members_end(); ++mb) {
    293       if (mb->second.first && mb->second.first->method) {
    294         if (!SWIG_Octave_InstallFunction(me, mb->first)) {
    295           return octave_value_list();
    296         }
    297       }
    298     }
    299 
    300 #if OCTAVE_API_VERSION_NUMBER < 37
    301     mlock(me->name());
    302 #else
    303     mlock();
    304 #endif
    305 
    306   }
    307 
    308   octave_swig_type::swig_member_const_iterator mb;
    309   for (mb = module_ns->swig_members_begin(); mb != module_ns->swig_members_end(); ++mb) {
    310     if (mb->second.second.is_defined()) {
    311       SWIG_Octave_SetGlobalValue(mb->first, mb->second.second);
    312       SWIG_Octave_LinkGlobalValue(mb->first);
    313     }
    314   }
    315 
    316   SWIG_Octave_SetGlobalValue(SWIG_name_d, module_ns->as_value());
    317   SWIG_Octave_LinkGlobalValue(SWIG_name_d);
    318 
    319   return octave_value_list();
    320 
    321 }
    322 
    323 %}
    324