New Octave module loading behaviour
- Use call syntax instead of cmdline to choose global/noglobal load: global: 'example;', noglobal: 'example = example;' - All functions loaded with Octave 'autoload' command; correctly loads .oct module and prevents segfault in Octave 3.0.5 - Functions no longer installed as global variables as well, so global operator dispatch now only looks for functions - Octave at-exit function created from string, not function, so no dependence on loaded .oct files at cleanup time - C at-exit function now immediately exits Octave (with correct status) to prevent seg-fault due to dodgy memory cleanup in some Octave versions - Documentation string for module loading function git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@13088 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
4f11aaa849
commit
bc2a78fbab
3 changed files with 146 additions and 174 deletions
|
|
@ -504,37 +504,9 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own);
|
|||
rhs.members.clear();
|
||||
}
|
||||
|
||||
void install_global(bool global_load) {
|
||||
for (member_map::const_iterator it = members.begin(); it != members.end(); ++it) {
|
||||
bool is_global_op = (it->first.substr(0, strlen(SWIG_op_prefix)) == SWIG_op_prefix);
|
||||
bool is_func_defined = (it->second.first && it->second.first->method);
|
||||
if (is_func_defined && (is_global_op || global_load)) {
|
||||
install_builtin_function(it->second.first->method, it->first,
|
||||
it->second.first->doc ? it->second.first->doc : std::string());
|
||||
}
|
||||
octave_value global_val = is_global_op ? make_fcn_handle(it->first) : it->second.second;
|
||||
if (global_val.is_defined() && (is_global_op || global_load)) {
|
||||
#if OCTAVE_API_VERSION_NUMBER<37
|
||||
link_to_global_variable(curr_sym_tab->lookup(it->first, true));
|
||||
#else
|
||||
symbol_table::varref(it->first);
|
||||
symbol_table::mark_global(it->first);
|
||||
#endif
|
||||
set_global_value(it->first, global_val);
|
||||
|
||||
#if OCTAVE_API_VERSION_NUMBER<37
|
||||
octave_swig_type *ost = Swig::swig_value_deref(global_val);
|
||||
if (ost) {
|
||||
const char* h = ost->help_text();
|
||||
if (h) {
|
||||
symbol_record *sr = global_sym_tab->lookup (it->first, true);
|
||||
sr->document(h);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
typedef member_map::const_iterator swig_member_const_iterator;
|
||||
swig_member_const_iterator swig_members_begin() { return members.begin(); }
|
||||
swig_member_const_iterator swig_members_end() { return members.end(); }
|
||||
|
||||
void *cast(swig_type_info *type, int *_own, int flags) {
|
||||
if (_own)
|
||||
|
|
@ -835,10 +807,10 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own);
|
|||
// we assume that SWIG_op_prefix-prefixed functions are installed in global namespace
|
||||
// (rather than any module namespace).
|
||||
|
||||
octave_value fcn = get_global_value(symbol, true);
|
||||
if (!fcn.is_function() && !fcn.is_function_handle())
|
||||
octave_function *fcn = is_valid_function(symbol, std::string(), false);
|
||||
if (!fcn)
|
||||
return false;
|
||||
ret = fcn.subsref("(", std::list < octave_value_list > (1, args), 1);
|
||||
ret = fcn->do_multi_index_op(1, args)(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
%insert(runtime) %{
|
||||
#include <iostream>
|
||||
#include <octave/oct.h>
|
||||
#include <octave/parse.h>
|
||||
#include <octave/ov-fcn-handle.h>
|
||||
#include <octave/Cell.h>
|
||||
#include <octave/dynamic-ld.h>
|
||||
#include <octave/oct-env.h>
|
||||
#include <octave/oct-map.h>
|
||||
#include <octave/ov-fcn-handle.h>
|
||||
#include <octave/parse.h>
|
||||
#include <octave/toplev.h>
|
||||
#include <octave/unwind-prot.h>
|
||||
%}
|
||||
|
||||
%insert(runtime) "swigrun.swg";
|
||||
|
|
@ -18,9 +21,12 @@
|
|||
|
||||
static void SWIG_init_user(octave_swig_type* module_ns);
|
||||
|
||||
#if OCTAVE_API_VERSION_NUMBER>=37
|
||||
octave_value_list SWIG_atexit_func(const octave_value_list &args, int nargout);
|
||||
#endif
|
||||
SWIGINTERN void SWIG_Octave_InstallFunction(octave_function *octloadfcn, std::string name) {
|
||||
octave_value_list args;
|
||||
args.append(name);
|
||||
args.append(octloadfcn->fcn_file_name());
|
||||
feval("autoload", args, 0);
|
||||
}
|
||||
|
||||
static const char *const subclass_usage = "-*- texinfo -*- \n\
|
||||
@deftypefn {Loadable Function} {} subclass()\n\
|
||||
|
|
@ -114,87 +120,94 @@ DEFUN_DLD( swig_this, args, nargout, swig_this_usage ) {
|
|||
return octave_value(octave_uint64((unsigned long long) ost->swig_this()));
|
||||
}
|
||||
|
||||
DEFUN_DLD (SWIG_name,args,nargout,SWIG_name_d) {
|
||||
|
||||
// determine if module is already loaded
|
||||
bool already_load;
|
||||
#if OCTAVE_API_VERSION_NUMBER<37
|
||||
{
|
||||
symbol_record *rec = curr_sym_tab->lookup(SWIG_name_d);
|
||||
already_load = (rec && rec->is_linked_to_global());
|
||||
}
|
||||
#else
|
||||
already_load = symbol_table::is_global(SWIG_name_d);
|
||||
// workaround to prevent octave seg-faulting on exit: register at-exit
|
||||
// function which exits octave immediately without trying to cleanup memory.
|
||||
// definitely affects version 3.2.*, not sure about 3.3.*, seems to be
|
||||
// fixed in version 3.4.* and above. can be turned on/off with macros.
|
||||
#ifndef SWIG_OCTAVE_NO_SEGFAULT_HACK
|
||||
#if 36 < OCTAVE_API_VERSION_NUMBER && OCTAVE_API_VERSION_NUMBER < 45
|
||||
#define SWIG_OCTAVE_SEGFAULT_HACK
|
||||
#endif
|
||||
if (!already_load) {
|
||||
|
||||
// parse command line
|
||||
const char* usage="usage: " SWIG_name_d " [-global|-noglobal] [-globals {<name>|.}]";
|
||||
bool global_load=SWIG_global_load;
|
||||
std::string global_name=SWIG_global_name;
|
||||
for (int j=0;j<args.length();++j)
|
||||
if (args(j).is_string()) {
|
||||
if (args(j).string_value()=="-help") {
|
||||
std::cout << usage << std::endl;
|
||||
return octave_value_list();
|
||||
} else if (args(j).string_value()=="-global") {
|
||||
global_load = true;
|
||||
} else if (args(j).string_value()=="-noglobal") {
|
||||
global_load = false;
|
||||
} else if (args(j).string_value()=="-globals") {
|
||||
if (j+1<args.length()&&args(j+1).is_string()) {
|
||||
global_name = args(j+1).string_value();
|
||||
++j;
|
||||
} else {
|
||||
std::cerr << "error: " SWIG_name_d ": option '-globals' requires an argument." << std::endl;
|
||||
std::cerr << usage << std::endl;
|
||||
return octave_value_list();
|
||||
}
|
||||
} else {
|
||||
std::cerr << "error: " SWIG_name_d ": unrecognised argument '" << args(j).string_value() << "'." << std::endl;
|
||||
std::cerr << usage << std::endl;
|
||||
return octave_value_list();
|
||||
}
|
||||
} else {
|
||||
std::cerr << "error: " SWIG_name_d ": unrecognised non-string argument." << std::endl;
|
||||
std::cerr << usage << std::endl;
|
||||
return octave_value_list();
|
||||
}
|
||||
|
||||
if (global_name != "." && !valid_identifier(global_name)) {
|
||||
std::cerr << "error: " SWIG_name_d ": '" << global_name << "' is not a valid Octave identifier." << std::endl;
|
||||
return octave_value_list();
|
||||
}
|
||||
|
||||
// load module in base frame
|
||||
#if OCTAVE_API_VERSION_NUMBER<37
|
||||
symbol_table *prev_sym_tab = curr_sym_tab;
|
||||
curr_sym_tab = top_level_sym_tab;
|
||||
#else
|
||||
octave_call_stack::goto_base_frame();
|
||||
#endif
|
||||
|
||||
#ifdef SWIG_OCTAVE_SEGFAULT_HACK
|
||||
#define _SWIG_OCT_SEGF_HACK_ATEXIT_FCN(NAME) SWIG_OCT_SEGF_HACK_ATEXIT_FCN_##NAME
|
||||
#define SWIG_OCT_SEGF_HACK_ATEXIT_FCN(NAME) _SWIG_OCT_SEGF_HACK_ATEXIT_FCN(NAME)
|
||||
void SWIG_OCT_SEGF_HACK_ATEXIT_FCN(SWIG_name)(void) {
|
||||
_exit(exit_status);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *const SWIG_name_usage = "-*- texinfo -*- \n\
|
||||
@deftypefn {Loadable Module} {} " SWIG_name_d "\n\
|
||||
Loads the SWIG-generated module `" SWIG_name_d "'.\n\
|
||||
\n\
|
||||
To load the module into the global namespace:\n\
|
||||
@example\n\
|
||||
" SWIG_name_d ";\n\
|
||||
@end example\n\
|
||||
To access the module through a local variable, without loading it globally:\n\
|
||||
@example\n\
|
||||
" SWIG_name_d " = " SWIG_name_d ";\n\
|
||||
@end example\n\
|
||||
To access the module locally through a variable named, e.g. @var{modl}:\n\
|
||||
@example\n\
|
||||
@var{modl} = " SWIG_name_d ";\n\
|
||||
@end example\n\
|
||||
@end deftypefn";
|
||||
|
||||
DEFUN_DLD( SWIG_name, args, nargout, SWIG_name_usage ) {
|
||||
|
||||
static octave_swig_type* module_ns = 0;
|
||||
octave_value_list retval;
|
||||
|
||||
// create module on first function call
|
||||
if (!module_ns) {
|
||||
|
||||
#ifdef SWIG_OCTAVE_SEGFAULT_HACK
|
||||
atexit(SWIG_OCT_SEGF_HACK_ATEXIT_FCN(SWIG_name));
|
||||
#endif
|
||||
|
||||
// workaround bug in octave where installing global variable of custom type and then
|
||||
// exiting without explicitly clearing the variable causes octave to segfault.
|
||||
#if OCTAVE_API_VERSION_NUMBER >= 37
|
||||
octave_value_list eval_args;
|
||||
eval_args.append("base");
|
||||
eval_args.append("function __swig_atexit__; "
|
||||
" if mislocked() "
|
||||
" clear -all; "
|
||||
" else "
|
||||
" mlock(); "
|
||||
" endif; "
|
||||
"endfunction; "
|
||||
"__swig_atexit__; "
|
||||
"atexit(\"__swig_atexit__\", false); "
|
||||
"atexit(\"__swig_atexit__\")");
|
||||
feval("evalin", eval_args, 0);
|
||||
#endif
|
||||
|
||||
octave_swig_ref::register_type();
|
||||
octave_swig_packed::register_type();
|
||||
SWIG_InitializeModule(0);
|
||||
SWIG_PropagateClientData();
|
||||
|
||||
install_builtin_function(swig_type,"swig_type",std::string());
|
||||
install_builtin_function(swig_typequery,"swig_typequery",std::string());
|
||||
install_builtin_function(swig_this,"swig_this",std::string());
|
||||
install_builtin_function(subclass,"subclass",std::string());
|
||||
|
||||
|
||||
octave_function *me = octave_call_stack::current();
|
||||
|
||||
SWIG_Octave_InstallFunction(me, "swig_type");
|
||||
SWIG_Octave_InstallFunction(me, "swig_typequery");
|
||||
SWIG_Octave_InstallFunction(me, "swig_this");
|
||||
SWIG_Octave_InstallFunction(me, "subclass");
|
||||
|
||||
octave_swig_type* cvar_ns=0;
|
||||
if (global_name != ".") {
|
||||
if (SWIG_global_name != ".") {
|
||||
cvar_ns=new octave_swig_type;
|
||||
for (int j=0;swig_globals[j].name;++j)
|
||||
if (swig_globals[j].get_method)
|
||||
cvar_ns->assign(swig_globals[j].name,&swig_globals[j]);
|
||||
}
|
||||
|
||||
octave_swig_type* module_ns=new octave_swig_type(0, 0, 0, true);
|
||||
if (global_name != ".") {
|
||||
module_ns->assign(global_name,Swig::swig_value_ref(cvar_ns));
|
||||
|
||||
module_ns=new octave_swig_type(0, 0, 0, true);
|
||||
if (SWIG_global_name != ".") {
|
||||
module_ns->assign(SWIG_global_name,Swig::swig_value_ref(cvar_ns));
|
||||
}
|
||||
else {
|
||||
for (int j=0;swig_globals[j].name;++j)
|
||||
|
|
@ -204,72 +217,63 @@ DEFUN_DLD (SWIG_name,args,nargout,SWIG_name_d) {
|
|||
for (int j=0;swig_globals[j].name;++j)
|
||||
if (swig_globals[j].method)
|
||||
module_ns->assign(swig_globals[j].name,&swig_globals[j]);
|
||||
|
||||
// * need better solution here; swig_type -> octave_class mapping is
|
||||
// * really n-to-1, in some cases such as template partial spec, etc.
|
||||
|
||||
// * need better solution here; swig_type -> octave_class mapping is
|
||||
// * really n-to-1, in some cases such as template partial spec, etc.
|
||||
// * see failing tests.
|
||||
for (int j=0;swig_types[j];++j)
|
||||
if (swig_types[j]->clientdata) {
|
||||
swig_octave_class* c=(swig_octave_class*)swig_types[j]->clientdata;
|
||||
module_ns->assign(c->name,
|
||||
Swig::swig_value_ref
|
||||
(new octave_swig_type(0,swig_types[j])));
|
||||
Swig::swig_value_ref
|
||||
(new octave_swig_type(0,swig_types[j])));
|
||||
}
|
||||
|
||||
SWIG_init_user(module_ns);
|
||||
|
||||
SWIG_InstallOps(octave_swig_ref::static_type_id());
|
||||
|
||||
// the incref is necessary so install_global doesn't destroy module_ns,
|
||||
// as it would if it installed something with the same name as the module.
|
||||
module_ns->incref();
|
||||
module_ns->install_global(global_load);
|
||||
module_ns->decref();
|
||||
|
||||
// create global variable containing module
|
||||
set_global_value(SWIG_name_d,Swig::swig_value_ref(module_ns));
|
||||
|
||||
#if OCTAVE_API_VERSION_NUMBER>=37
|
||||
install_builtin_function(SWIG_atexit_func,"__swig_atexit_" SWIG_name_d "__",std::string());
|
||||
octave_add_atexit_function("__swig_atexit_" SWIG_name_d "__");
|
||||
octave_remove_atexit_function("__finish__");
|
||||
#endif
|
||||
|
||||
// return from base frame
|
||||
#if OCTAVE_API_VERSION_NUMBER<37
|
||||
curr_sym_tab = prev_sym_tab;
|
||||
SWIG_init_user(module_ns);
|
||||
|
||||
SWIG_InstallOps(octave_swig_ref::static_type_id());
|
||||
|
||||
#if OCTAVE_API_VERSION_NUMBER < 37
|
||||
mlock(me->name());
|
||||
#else
|
||||
octave_call_stack::pop();
|
||||
#endif
|
||||
|
||||
#if OCTAVE_API_VERSION_NUMBER>=37
|
||||
mlock();
|
||||
#endif
|
||||
|
||||
} // !already_load
|
||||
|
||||
// link variable to module in current context
|
||||
#if OCTAVE_API_VERSION_NUMBER<37
|
||||
link_to_global_variable(curr_sym_tab->lookup(SWIG_name_d,true));
|
||||
#else
|
||||
symbol_table::varref(SWIG_name_d);
|
||||
symbol_table::mark_global(SWIG_name_d);
|
||||
#endif
|
||||
}
|
||||
|
||||
return octave_value_list();
|
||||
}
|
||||
// return module if asked for
|
||||
if (args.length() == 0 && nargout == 1) {
|
||||
retval = octave_value(module_ns->as_value());
|
||||
}
|
||||
|
||||
// if call with not output arguments, load globally
|
||||
else if (args.length() == 0 && nargout == 0) {
|
||||
|
||||
octave_function *me = octave_call_stack::current();
|
||||
|
||||
octave_swig_type::swig_member_const_iterator mb;
|
||||
for (mb = module_ns->swig_members_begin(); mb != module_ns->swig_members_end(); ++mb) {
|
||||
if (mb->second.first && mb->second.first->method) {
|
||||
SWIG_Octave_InstallFunction(me, mb->first);
|
||||
}
|
||||
else if (mb->second.second.is_defined()) {
|
||||
SWIG_Octave_SetGlobalValue(mb->first, mb->second.second);
|
||||
SWIG_Octave_LinkGlobalValue(mb->first);
|
||||
}
|
||||
}
|
||||
|
||||
SWIG_Octave_SetGlobalValue(SWIG_name_d, module_ns->as_value());
|
||||
SWIG_Octave_LinkGlobalValue(SWIG_name_d);
|
||||
|
||||
}
|
||||
|
||||
// otherwise print usage
|
||||
else {
|
||||
print_usage();
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
||||
// workaround bug in octave where installing global variable of custom type and then
|
||||
// exiting without explicitly clearing the variable causes octave to segfault.
|
||||
#if OCTAVE_API_VERSION_NUMBER>=37
|
||||
octave_value_list SWIG_atexit_func(const octave_value_list &args, int nargout) {
|
||||
string_vector vars = symbol_table::global_variable_names();
|
||||
for (int i = 0; i < vars.length(); i++)
|
||||
symbol_table::clear_global(vars[i]);
|
||||
symbol_table::clear_functions();
|
||||
return octave_value();
|
||||
}
|
||||
#endif
|
||||
|
||||
%}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,16 +15,13 @@ char cvsroot_octave_cxx[] = "$Id$";
|
|||
|
||||
#include "swigmod.h"
|
||||
|
||||
static bool global_load = true;
|
||||
static String *global_name = 0;
|
||||
static String *op_prefix = 0;
|
||||
|
||||
static const char *usage = (char *) "\
|
||||
Octave Options (available with -octave)\n\
|
||||
-global - Load all symbols into the global namespace [default]\n\
|
||||
-globals <name> - Set <name> used to access C global variables [default: 'cvar']\n\
|
||||
- Use '.' to load C global variables into module namespace\n\
|
||||
-noglobal - Do not load all symbols into the global namespace\n\
|
||||
Use '.' to load C global variables into module namespace\n\
|
||||
-opprefix <str> - Prefix <str> for global operator functions [default: 'op_']\n\
|
||||
\n";
|
||||
|
||||
|
|
@ -83,12 +80,13 @@ public:
|
|||
if (argv[i]) {
|
||||
if (strcmp(argv[i], "-help") == 0) {
|
||||
fputs(usage, stdout);
|
||||
} else if (strcmp(argv[i], "-global") == 0) {
|
||||
global_load = true;
|
||||
Swig_mark_arg(i);
|
||||
} else if (strcmp(argv[i], "-noglobal") == 0) {
|
||||
global_load = false;
|
||||
Swig_mark_arg(i);
|
||||
} else if (strcmp(argv[i], "-global") == 0 ||
|
||||
strcmp(argv[i], "-noglobal") == 0) {
|
||||
Printv(stderr,
|
||||
"*** -global/-noglobal are no longer supported\n"
|
||||
"*** global load behaviour is now determined at module load\n"
|
||||
"*** see the Perl section in the manual for details.\n", NIL);
|
||||
SWIG_exit(EXIT_FAILURE);
|
||||
} else if (strcmp(argv[i], "-globals") == 0) {
|
||||
if (argv[i + 1]) {
|
||||
global_name = NewString(argv[i + 1]);
|
||||
|
|
@ -179,10 +177,8 @@ public:
|
|||
Printf(f_runtime, "#define SWIG_name %s\n", module);
|
||||
|
||||
Printf(f_runtime, "\n");
|
||||
Printf(f_runtime, "#define SWIG_global_load %s\n", global_load ? "true" : "false");
|
||||
Printf(f_runtime, "#define SWIG_global_name \"%s\"\n", global_name);
|
||||
Printf(f_runtime, "#define SWIG_op_prefix \"%s\"\n", op_prefix);
|
||||
Printf(f_runtime, "#define SWIG_atexit_func swig_atexit_%s\n", module);
|
||||
|
||||
if (directorsEnabled()) {
|
||||
Printf(f_runtime, "#define SWIG_DIRECTORS\n");
|
||||
|
|
@ -383,7 +379,7 @@ public:
|
|||
virtual int importDirective(Node *n) {
|
||||
String *modname = Getattr(n, "module");
|
||||
if (modname)
|
||||
Printf(f_init, "feval(\"%s\",octave_value_list(),0);\n", modname);
|
||||
Printf(f_init, "feval(\"%s\",octave_value_list(),1);\n", modname);
|
||||
return Language::importDirective(n);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue