Changes Octave module loading behavior, so that modules can be safely loaded inside functions without first being loaded at the base level. (Basically the module is now always loaded in the base context, and then a local link to the module is created in the current context.) Added an example, module_load, to Examples/octave to test this behaviour in different ways. Tested examples work for octave 3.0.5, 3.2.4, and 3.4.0. (thanks to Karl Wette)
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12793 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
b61ccd00ec
commit
3372c2ba62
12 changed files with 251 additions and 79 deletions
|
|
@ -366,7 +366,9 @@ octave_cpp: $(SRCS)
|
|||
OCTSCRIPT = runme.m
|
||||
|
||||
octave_run: $(OCTSCRIPT)
|
||||
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH OCTAVEPATH=$(srcdir):$$OCTAVEPATH $(OCTAVE) $(OCTSCRIPT) >/dev/null
|
||||
for file in $(OCTSCRIPT); do \
|
||||
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH OCTAVEPATH=$(srcdir):$$OCTAVEPATH $(OCTAVE) $$file >/dev/null || break; \
|
||||
done
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Cleaning the octave examples
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ funcptr
|
|||
funcptr2
|
||||
functor
|
||||
operator
|
||||
module_load
|
||||
pointer
|
||||
reference
|
||||
simple
|
||||
|
|
|
|||
26
Examples/octave/module_load/Makefile
Normal file
26
Examples/octave/module_load/Makefile
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
TOP = ../..
|
||||
SWIG = $(TOP)/../preinst-swig
|
||||
SRCS = example.c
|
||||
TARGET = example
|
||||
INTERFACE = example.i
|
||||
OCTSCRIPTS = \
|
||||
runme_args.m \
|
||||
runme_gl_func.m \
|
||||
runme_gl_func_base.m \
|
||||
runme_nogl_func.m \
|
||||
runme_nogl_func_base.m
|
||||
|
||||
all::
|
||||
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
|
||||
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave
|
||||
|
||||
static::
|
||||
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
|
||||
TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_static
|
||||
|
||||
clean::
|
||||
$(MAKE) -f $(TOP)/Makefile octave_clean
|
||||
rm -f $(TARGET).m
|
||||
|
||||
check: all
|
||||
$(MAKE) -f $(TOP)/Makefile OCTSCRIPT="$(OCTSCRIPTS)" octave_run
|
||||
9
Examples/octave/module_load/example.c
Normal file
9
Examples/octave/module_load/example.c
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* File : example.c */
|
||||
|
||||
#include "example.h"
|
||||
|
||||
int ivar = 47;
|
||||
|
||||
int ifunc() {
|
||||
return ivar;
|
||||
}
|
||||
5
Examples/octave/module_load/example.h
Normal file
5
Examples/octave/module_load/example.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/* File: example.h */
|
||||
|
||||
extern int ivar;
|
||||
|
||||
int ifunc();
|
||||
9
Examples/octave/module_load/example.i
Normal file
9
Examples/octave/module_load/example.i
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* File : example.i */
|
||||
%module example
|
||||
%{
|
||||
#include "example.h"
|
||||
%}
|
||||
|
||||
extern "C" int ivar;
|
||||
|
||||
int ifunc();
|
||||
12
Examples/octave/module_load/runme_args.m
Normal file
12
Examples/octave/module_load/runme_args.m
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# file: runme_args.m
|
||||
|
||||
# test module loading with arguments
|
||||
|
||||
# test help
|
||||
example -help
|
||||
assert(!isglobal("example"))
|
||||
|
||||
# load module with custom cvar
|
||||
example -globals mycvar
|
||||
assert(!isglobal("cvar"))
|
||||
assert(mycvar.ivar == example.ifunc())
|
||||
21
Examples/octave/module_load/runme_gl_func.m
Normal file
21
Examples/octave/module_load/runme_gl_func.m
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# file: runme_gl_func.m
|
||||
|
||||
# test whether module can be loaded
|
||||
# in a function (global cvar)
|
||||
|
||||
# test that everything works from the base context
|
||||
example
|
||||
global cvar
|
||||
assert(cvar.ivar == example.ifunc())
|
||||
|
||||
function func
|
||||
example
|
||||
global cvar
|
||||
assert(cvar.ivar == example.ifunc())
|
||||
endfunction
|
||||
|
||||
# test loading in a function
|
||||
func
|
||||
|
||||
# test a second time to check everything works
|
||||
func
|
||||
23
Examples/octave/module_load/runme_gl_func_base.m
Normal file
23
Examples/octave/module_load/runme_gl_func_base.m
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# file: runme_gl_func_base.m
|
||||
|
||||
# test whether module can be loaded in a function
|
||||
# before the base context (global cvar)
|
||||
|
||||
1;
|
||||
|
||||
function func
|
||||
example
|
||||
global cvar
|
||||
assert(cvar.ivar == example.ifunc())
|
||||
endfunction
|
||||
|
||||
# test loading in a function
|
||||
func
|
||||
|
||||
# test a second time to check everything works
|
||||
func
|
||||
|
||||
# test that everything works from the base context
|
||||
example
|
||||
global cvar
|
||||
assert(cvar.ivar == example.ifunc())
|
||||
19
Examples/octave/module_load/runme_nogl_func.m
Normal file
19
Examples/octave/module_load/runme_nogl_func.m
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# file: runme_nogl_func.m
|
||||
|
||||
# test whether module can be loaded
|
||||
# in a function (no global cvar)
|
||||
|
||||
# test that everything works from the base context
|
||||
example -noglobal
|
||||
assert(example.cvar.ivar == example.ifunc())
|
||||
|
||||
function func
|
||||
example -noglobal
|
||||
assert(example.cvar.ivar == example.ifunc())
|
||||
endfunction
|
||||
|
||||
# test loading in a function
|
||||
func
|
||||
|
||||
# test a second time to check everything works
|
||||
func
|
||||
21
Examples/octave/module_load/runme_nogl_func_base.m
Normal file
21
Examples/octave/module_load/runme_nogl_func_base.m
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# file: runme_nogl_func_base.m
|
||||
|
||||
# test whether module can be loaded in a function
|
||||
# before the base context (no global cvar)
|
||||
|
||||
1;
|
||||
|
||||
function func
|
||||
example -noglobal
|
||||
assert(example.cvar.ivar == example.ifunc())
|
||||
endfunction
|
||||
|
||||
# test loading in a function
|
||||
func
|
||||
|
||||
# test a second time to check everything works
|
||||
func
|
||||
|
||||
# test that everything works from the base context
|
||||
example -noglobal
|
||||
assert(example.cvar.ivar == example.ifunc())
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
#include <octave/ov-fcn-handle.h>
|
||||
#include <octave/Cell.h>
|
||||
#include <octave/oct-map.h>
|
||||
#include <octave/toplev.h>
|
||||
%}
|
||||
|
||||
%insert(runtime) "swigrun.swg";
|
||||
|
|
@ -18,103 +19,126 @@
|
|||
static void SWIG_init_user(octave_swig_type* module_ns);
|
||||
|
||||
DEFUN_DLD (SWIG_name,args,nargout,SWIG_name_d) {
|
||||
static bool already_init=false;
|
||||
if (already_init)
|
||||
return octave_value_list();
|
||||
|
||||
// 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;
|
||||
static bool already_init=false;
|
||||
static octave_swig_type* module_ns=0;
|
||||
|
||||
// if module not already loaded
|
||||
if (!already_init) {
|
||||
|
||||
// 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 ": option '-globals' requires an argument." << std::endl;
|
||||
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 argument '" << args(j).string_value() << "'." << std::endl;
|
||||
std::cerr << "error: " SWIG_name_d ": unrecognised non-string argument." << 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;
|
||||
|
||||
if (!valid_identifier(global_name)) {
|
||||
std::cerr << "error: " SWIG_name_d ": '" << global_name << "' is not a valid Octave identifier." << std::endl;
|
||||
return octave_value_list();
|
||||
}
|
||||
|
||||
if (!valid_identifier(global_name)) {
|
||||
std::cerr << "error: " SWIG_name_d ": '" << global_name << "' is not a valid Octave identifier." << std::endl;
|
||||
return octave_value_list();
|
||||
}
|
||||
|
||||
already_init=true;
|
||||
|
||||
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(swig_subclass,"subclass",std::string());
|
||||
|
||||
octave_swig_type* 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);
|
||||
module_ns->assign(global_name,Swig::swig_value_ref(cvar_ns));
|
||||
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.
|
||||
// * 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_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();
|
||||
already_init=true;
|
||||
|
||||
// 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
|
||||
|
||||
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(swig_subclass,"subclass",std::string());
|
||||
|
||||
octave_swig_type* 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]);
|
||||
|
||||
module_ns=new octave_swig_type(0, 0, 0, true);
|
||||
module_ns->assign(global_name,Swig::swig_value_ref(cvar_ns));
|
||||
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.
|
||||
// * 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_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));
|
||||
|
||||
// return from base frame
|
||||
#if OCTAVE_API_VERSION_NUMBER<37
|
||||
curr_sym_tab = prev_sym_tab;
|
||||
#else
|
||||
octave_call_stack::pop();
|
||||
#endif
|
||||
|
||||
#if OCTAVE_API_VERSION_NUMBER>=37
|
||||
mlock();
|
||||
#endif
|
||||
|
||||
} // !already_init
|
||||
|
||||
// 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
|
||||
set_global_value(SWIG_name_d,Swig::swig_value_ref(module_ns));
|
||||
|
||||
#if OCTAVE_API_VERSION_NUMBER>=37
|
||||
mlock();
|
||||
#endif
|
||||
|
||||
return octave_value_list();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue